@Modifying 어노테이션은 @Query 어노테이션으로 작성된 INSERT, UPDATE, DELETE 쿼리를 사용할 때 필요하며(SELECT 제외), 주로 다중 UPDATE 또는 DELETE 같은 복잡한 벌크 연산을 하나의 쿼리로 수행할 때 사용한다.
INSERT, UPDATE, DELETE 쿼리에서 @Modifying 어노테이션을 사용하지 않는 경우에는 아래와 같은 오류가 발생한다.
org.hibernate.hql.internal.QueryExecutionRequestException: Not supported for DML operations [update ...]
@Modifying 어노테이션을 적용하게 되면 JPA Entity Life Cycle을 무시하고 쿼리가 실행되기 때문에 영속성 컨텍스트 관리에 주의해야 한다.
해당 속성은 @Query와 @Modifying을 통한 쿼리 메서드를 사용할 때, 해당 쿼리를 실행하기 전, 영속성 컨텍스트의 변경 사항을 Database에 flush 할 것인지를 결정하는 속성이다.
해당 속성은 @Modifying이 적용된 쿼리 메서드를 실행한 후, 영속성 컨텍스트를 clear 할 것인지를 지정하는 속성이다.
주목해야 하는 부분은 'Persistent' 즉, 영속 상태입니다.
쉽게 객체를 저장한 상태라고 이해할 수 있는데, save() 메서드를 통해 ID를 할당하며, 이후 트랜잭션이 끝날 때까지 모든 변경 사항을 감지하고 동기화하는 상태이다.
Persistent 상태에서는 하이버네이트가 한 트랜잭션 내에서 불필요한 쿼리를 줄여주는 중요한 역할을 하는데, 흔히 1차 캐시라고 부르는 영속성 컨텍스트(Persistent Context)가 해당 인스턴스를 이미 담고 있기 때문에 SELECT 요청을 하더라도 DB에 접근하지 않고, Persisent Context에 저장된 인스턴스를 반환하게 된다.
결론적으로 @Query와 @Modifying을 사용한 벌크 연산에서는 1차 캐시를 포함한 영속성 컨텍스트를 무시하고 바로 쿼리를 실행하기 때문에 영속성 컨텍스트는 데이터 변경을 알 수 없다. 즉, 1차 캐시(Persistent ConText)와 DB에 데이터가 일치하지 않을 수 있다.
먼저 테스트한 속성 값이 false일 때와의 차이점은 update 문 이후 select 문이 한번 더 날아갔다는 점이다.
clearAutomatically = true. 즉, @Modifying 어노테이션이 적용된 쿼리 메서드를 실행한 후, 영속성 컨텍스트(Persistent Context)에 담겨있는 인스턴스를 clear 했다는 것이다.