순수 Repository에도 락을 걸 수 있을까요?
246
코린코린
작성한 질문수 53
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));
}
항상 좋은 강의와 답변 감사드립니다.
답변 1
changeTeam 메서드 질문
0
34
1
existsByUserIdAndProjectId vs existsByUserAndProject 중 어떤 방식이 적절할까요?
0
87
1
existsByUserIdAndProjectId vs existsByUserAndProject 중 어떤 방식이 적절할까요?
0
128
3
MemberRepository 구현체
0
71
1
pdf 표현 질문드립니다.
0
77
1
로그가 남지 않는 문제.
0
98
1
테스트 라이브러리가 강의는 junit4가 맞나요??
0
78
2
pdf 파일과 차이점이 있는 것같은데 문제 없나요?
0
75
2
@PrePersist, @PreUpdate 호출 시점 질문드립니다.
0
102
2
Sort 인터페이스는 잘 사용 안하나요?
0
59
1
스캔대상 질문드립니다.
0
48
1
하이버네이트6에서의 최적화에 이은 질문
0
92
1
save() vs saveAndFlush DB 통신 횟수
0
58
1
순수 JPA 리포지토리 코드 수정부분
0
92
2
bulk연산 후 flush하는 이유를 모르겠어요
0
163
3
bulk insert 질문입니다.
0
191
2
교만했던 것 같아요.
0
152
1
RESTful 강의는 안하시는 건지 궁금합니다.
0
154
2
동적 테이블에 대한 질문
0
89
1
영속성 전이와 연관관계
0
141
2
강의 10:25 질문
0
78
1
단건 update 질문
0
104
2
엔티티 와 도메인의 경계
0
129
1
UsernameOnlyDto 타입 type mismatch 오류
0
123
1





