스프링 데이터 JPA는 @Lock 애너테이션을 사용해 잠금 모드를 지정한다.
@Lock(LockMode.Type.PESSIMISTIC_WRITE)
@Query("select m from Member m where m.id = :id")
Optional<Member> findByIdForUpdate(@Param("id") MemberId memberId);
스프링 데이터 JPA는 @QueryHints
애너테이션을 통해 쿼리 힌트를 지정할 수 있다.
@Lock(LockMode.Type.PESSIMISTIC_WRITE)
@QueryHints({
@QueryHint(name = "javax.persistence.lock.timeout", value = "2000)
})
@Query("select m from Member m where m.id = :id")
Optional<Member> findByIdForUpdate(@Param("id") MemberId memberId);
UPDATE aggtable SET version = version + 1, colx = ?, coly = ?
WHERE aggid = ? and version = 현재_버전
JPA에서 비선점 잠금을 이용하려면 @Version
을 사용할 수 있다.
@Entity
public class Order {
// ...
@Version
private Long version;
// ...
}
@Version
에 명시한 필드를 이용해 비선점 잠금 쿼리를 실행한다.OptimisticLockingFailureException
이 발생위 현상이 도메인 일관성을 깨뜨린다면 강제로 버전 값을 증가시킬 수도 있다.
@Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
@Query("select m from Member m where m.id = :id")
Optional<Member> findByIdForUpdate(@Param("id") MemberId memberId);
LockModeType.OPTIMISTIC_FORCE_INCREMENT
를 사용하면 엔티티가 변경되었는지에 상관 없이 버전 값 증가 처리를 한다.