-
카테고리
-
세부 분야
백엔드
-
해결 여부
미해결
순수 Repository에도 락을 걸 수 있을까요?
22.02.04 10:11 작성 조회수 160
0
안녕하세요.
항상 좋은 강의와 답변 주셔서 감사합니다.
강의를 다 듣지 못해서 ㅠㅠ... 죄송하지만..
여기에 글을 적게 되었습니다.
제가 JPA의 DB쪽 동시성 병렬성 문제를 고민하던 중... @Lcok이라는 기능을 통해 DB쪽 문제까지 해결할 수 있다는 것을 알게 되어서... @LOCK을 순수 Repository나 Service에 걸려고 했었습니다.
그런데 하다 보니 @Lock이 Spring Data JPA 패키지에 있더라구요. 그래서 구글링을 해보니 많은 분들께서 JPA Repository 구현체에다가 @Lock을 적용하시는 것 같았습니다.
혹시 Spring Data Jpa Repository의 구현체가 아닌 순수 JPA에서도 @Lock 어노테이션을 정상적으로 사용할 수 있을까요?
제가 비관적 락을 걸고, Version으로 관리하는 코드를 작성해서 돌려봤는데... 비관적 락이 아니라, default인 낙관적 락으로 계속 돌아가는 것 같습니다... 다른 분들이 자겅한 코드를 확인해보니, JPA Repository 구현체에서는 정상적으로 @Lock이 먹히는 거 같습니다...
혹시 바쁘시겠지만... 알려주시면 너무 감사드리겠습니다...!
엔티티 코드
@Entity
@Data
public class MyEntity {
@Id
@GeneratedValue
private Long id;
private Long num;
@Version
private Long version;
}
리포지토리 코드
@Repository
@RequiredArgsConstructor
public class MyRepository {
private final EntityManager em;
@Transactional
@Lock(value = LockModeType.PESSIMISTIC_FORCE_INCREMENT)
public MyEntity save(MyEntity entity) {
em.persist(entity);
return entity;
}
public MyEntity findById(Long entityId) {
return em.find(MyEntity.class, entityId);
}
}
서비스 코드
@Service
@RequiredArgsConstructor
public class MyService {
private final MyRepository myRepository;
@Transactional
public MyEntity save(MyEntity entity) {
entity.setNum(entity.getNum() + 1);
myRepository.save(entity);
return entity;
}
@Transactional
public MyEntity saveEntity(Long entityId) {
MyEntity entity = myRepository.findById(entityId);
entity.setNum(entity.getNum() + 1);
myRepository.save(entity);
return entity;
}
}
테스트 코드 --> 돌리는 도중 낙관적 락에 의한 예외 코드 발생하며 종료
@SpringBootTest
public class MyEntityTest {
private static final ExecutorService service =
Executors.newFixedThreadPool(3);
@Autowired
private MyRepository myRepository;
@Autowired
private MyService myService;
private long accountId;
private Long entityId;
@BeforeEach
public void setUp() {
MyEntity myEntity = new MyEntity();
myEntity.setNum(10L);
myService.save(myEntity);
entityId = myEntity.getId();
}
@Test
public void raceCond() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
service.execute(() -> {
myService.saveEntity(entityId);
latch.countDown();
});
}
latch.await();
System.out.println("myRepository.findById(entityId) = " + myRepository.findById(entityId));
}
항상 좋은 강의와 답변 감사드립니다.
답변을 작성해보세요.
0
답변 1