SQL에서 Hint를 사용하듯이 JPA에서도 JPA 구현체에 힌트를 전달할 수 있다. 이번 포스팅에서는 JPA의 Hint와 Lock에 대해서 알아보고자 한다.
기본적으로 JPA를 이용해 데이터를 조회하게되면 영속성 컨텍스트에 저장되어 관리되고, 그 값을 수정하면 변경 감지 기능에 의해 자동으로 업데이트 쿼리가 실행된다. (수동으로 직접 flush()를 할 수도 있음)
이때 Hint
기능을 사용하여 영속성 컨텍스트에 저장되는 것을 방지해 메모리 낭비를 막고 혹시 모를 변경사항에 대해 업데이트되지 않도록 설정할 수 있다.
@QueryHints(value = @QueryHint(name = "org.hibernate.readOnly", value = "true"))
Member findReadOnlyByUsername(String username);
아래 테스트 코드를 실행해보면 업데이트 쿼리가 실행되지 않는 것을 확인할 수 있다.
@Test
public void queryHint() throws Exception {
//given
memberRepository.save(new Member("member1", 10));
em.flush();
em.clear();
//when
Member member = memberRepository.findReadOnlyByUsername("member1");
member.setUsername("member2");
em.flush(); //Update Query 실행X
}
org.springframework.data.jpa.repository.QueryHints 어노테이션 사용
forCounting : 반환 타입으로 Page 인터페이스를 적용하면 추가로 호출하는 페이징을 위한 count 쿼리도 쿼리 힌트 적용 (기본값 true)
@QueryHints(value = { @QueryHint(name = "org.hibernate.readOnly", value = "true")}, forCounting = true)
Page<Member> findByUsername(String name, Pageable pageable);
JPA에서 지원하는 Lock
기능을 스프링 데이터 JPA에서는 단순히 애너테이션만 추가해서 사용할 수 있다. (org.springframework.data.jpa.repository.Lock 어노테이션 사용)
@Lock(LockModeType.PESSIMISTIC_WRITE)
List<Member> findByUsername(String name);