public interface MemberRepository extends JpaRepository<Member, Long> {
@QueryHints(value = @QueryHint(name = "org.hibernate.readOnly", value = "true"))
Member findReadOnlyByUsername(String username);
}
@SpringBootTest
@Transactional
@Rollback(value = false)
class MemberRepositoryTest {
@Test
public void queryHint() throws Exception {
memberRepository.save(new Member("member1", 10));
// DB에 동기화
em.flush();
// 영속성 컨텍스트 초기화
em.clear();
// 영속성 컨텍스트를 초기화 했으니 무조건 DB에 쿼리를 날린다.
Member member = memberRepository.findReadOnlyByUsername("member1");
member.setUsername("member2");
// 더티 체킹이 반영되지 않는다.
em.flush();
}
}
insert into member (age, team_id, username, member_id)
values (10, NULL, 'member1', 1);
select member0_.member_id as member_i1_0_,
member0_.age as age2_0_,
member0_.team_id as team_id4_0_,
member0_.username as username3_0_
from member member0_
where member0_.username = 'member1';
더티 체킹은 원본과 수정본을 둘 다 메모리에 들고 있어야 하고 체크하는 과정도 필요하기 때문에 비용이 든다.
@SpringBootTest
@Transactional
@Rollback(value = false)
class MemberRepositoryTest {
@Test
public void lock() {
memberRepository.save(new Member("member1", 10));
em.flush();
em.clear();
List<Member> members = memberRepository.findByUsername("member1");
}
}
select member0_.member_id as member_i1_0_,
member0_.age as age2_0_,
member0_.team_id as team_id4_0_,
member0_.username as username3_0_
from member member0_
where member0_.username = 'member1' for update;