[JPA] 영속성 컨텍스트의 DB동기화와 flush 시점

김형진·2023년 5월 4일
0

commit시점에 발생하는 update쿼리가 아니라 직접 update쿼리를 보내는 경우 영속성 컨텍스트에 변경내용이 반영되지 않는다.

새로운 Member객체를 생성하고 save하여 영속성 컨텍스트에 캐싱한 뒤
(커밋 시점의 더티체킹 후 update쿼리가 아닌) update쿼리를 직접 날리면 영속성 컨텍스트는 알지 못한다.

그렇다면 현재 영속성 컨텍스트에서 관리되고 있는 Member객체를 DB에 저장된 Member와 동기화한 뒤 사용해야 하는데 이는

//client
memberRepository.save(new Member("memberA",10));
memberRepository.updateMemberAge(); // 전체 Member의 age를 +1
entityManager.clear(); //EntityManager를 직접 의존주입 받음
memberRepository.findByName("memberA");

와 같이 update쿼리 이후 영속성 컨텍스트를 초기화한 뒤 Member객체를 다시 조회하거나

// Repository Interface
@Modifying(clearAutomatically = true)
@Query("update Member m set m.age = m.age + 1")
int updateMemberAge();

와 같이 Update쿼리에 필수인 Modifying 어노테이션의 옵션인 clearAutomatically를 true로 설정하면 update쿼리 이후 영속성 컨텍스트를 초기화할 수 있다.

그리고 새로 생성한 member객체를 영속성관리하고 있지만 아직 commit되지 않았기 때문에 변경사항이 있을 수 있으니 강제 flush 해줘야겠다 라고 생각해 원래는

//client
memberRepository.save(new Member("memberA",10));
entityManager.flush();
memberRepository.updateMemberAge(); // 전체 Member의 age를 +1
entityManager.clear(); //EntityManager를 직접 의존주입 받음
memberRepository.findByName("memberA");

와 같이 update쿼리 이전에 직접 flush 했지만 생각해보니 그럴 필요가 없었다. JPQL실행 이전엔 자동으로 영속성 컨텍스트의 내용이 flush되기 때문이다.

Spring Data JPA를 이용해서 update쿼리를 명시하는 것도 결국 JPQL을 사용하는 것이기 때문에 직접 flush할 필요가 없다.

profile
히히

0개의 댓글