개발/Spring
Spring - JPA (3) update 쿼리와 영속성 컨텍스트
로그뉴
2022. 7. 12. 13:38
기본적으로 JPA에서 update를 하려면 다음과 같이 진행하는 것이 일반적이다.
|
@Modifying
@Query("UPDATE Post p SET p.title = :title WHERE p.id = :id")
int updateTitle(String title, Long id);
|
예제 step
- 저장 - Post 객체 save()
- 수정 - post.updateTitle("변경진행")
- 조회 - findById(post.getId())
위와 같은 코드를 짰을 때, 발생하는 문제점은 다음과 같다.
updateTitle 함수 실행 후, 객체를 확인하면 값이 변경되어 있지 않다.
- findById()를 호출시, select 쿼리는 수행되지 않는다.
- → 이유: findById()는 DB를 확인하기 전에 우선적으로 영속성 컨텍스트(1차 캐시)에 찾으려는 Id의 엔티티가 존재하는지를 확인하기 때문.
- findById() 호출전에 post.save()를 호출했는데 이 때, 영속성 컨텍스트에 post가 저장 되었음.
- 따라서, 영속성 컨텍스트에 있는 p를 그대로 반환하게 되고, 이 때의 p의 title 값은 수정 전 값이 된다.
영속성 컨텍스트에 있는 값이 반환되는 이유
- 트랜잭션이 아직 끝나지 않고 캐시가 비워지지 않았기 때문에 spring 객체가 PersistenceContext에 그대로 있어서 spring 객체는 계속해서 persist 상태의 객체임
- persist 상태의 객체는 1차 캐시 즉, PersistenceContext가 관리하고 있음
- 그 상태 에서 find를 하면 DB를 가지 않음. 자기자신이 캐싱하고 있던 것을 그대로 가지고 옴.
- 따라서, 데이터베이스의 Update 쿼리가 발생했지만 spring 객체는 persist 상태의 객체이므로 캐시에 남아있었기 떄문에 수정된 값을 확인할 수 없는 것.
해결법
- @Modifying(clearAutomatically = true, flushAutomatically = true)
- persist context에 쌓여있던 캐시를 비워주는 옵션. 권장하지 않음.