벌크 연산과 @Modifying 어노테이션
서버개발

벌크 연산과 @Modifying 어노테이션

요약

JPA를 이용하게 되어도 쿼리를 작성해야하는 순간이 오는데 다중 write 연산인 Bulk 연산과 @Modifying 어노테이션에 대해서 정리하였다. JPA는 영속성 컨텍스트에 오브젝트를 캐싱하는데 이때 @Modifying 설정에 따라 캐싱된 데이터와 DB의 데이터가 일관하지 않을 수 있다. 이를 고려하여 코드를 작성하여야 한다.

  • @Modifying
    • @Query 어노테이션(JPQL Query, Native Query)을 통해 작성된 insert, update, delete 쿼리에서 사용되는 어노테이션
    • 기본적으로 JpaRepository에서 제공하는 메서드 혹은 메서드 네이밍으로 만들어진 쿼리에는 적용되지 않는다
    • clearAutomatically, flushAutomactically 속성 변경 가능
    • Jpa Entity Life-Cycle을 무시하고 쿼리가 실행되기 때문에 영속성 컨텍스트 관리에 주의
  • Bulk 연산이란
    • 단 건에 대한 update, delete 연산이 아닌 다중 건에 대한 update, delete 연산을 하나의 쿼리로 하는 것
    • jpa에서 단 건의 update의 경우에는 변경 감지를 통해 수행되거나 save를 통해 수행할 수 있다
    • delete는 단 건, 다중 건 쿼리 메서드로 제공된다
  • @Modifiying과 Bulk 연산
    • 이 방법을 사용하면 JPQL을 자유롭게 정의하여 사용, 하나의 쿼리로 많은 데이터를 변경할 수 있다
    • @Query에 벌크 연산 쿼리를 작성하고, @Modifying 어노테이션을 붙이지 않으면 InvalidDataAccessApiUsageException 발생
      • @Modifiying이 붙은 해당 쿼리 메서드 실행 직후, 영속성 컨텍스트를 clear할 것인지 지정하는 속성
      • default는 false이며 false인 경우 영속성 컨텍스트 1차 캐시와 관련된 문제 발생 가능성 有
      • jpa에서 영속성 컨텍스트의 1차 캐시를 통해 엔티티 캐싱, DB의 접근 횟수를 줄임으로 성능 개선
      • 1차 캐시는 @Id값을 키 값으로 엔티티 관리
      • JPA의 1차 캐시는 DB에 접근 횟수를 줄여 성능을 개선하는 좋은 기능이지만 @Modifying과 @Query를 이용한 벌크 연산에서는 이 기능때문에 예측하지 못한 결과가 나올 수 있다.
        clearAutomatically 속성

JPA에서 조회를 실행할 때, 1차 캐시를 확인해서 해당 엔티티가 1차 캐시에 존재한다면 DB에 접근하지 않고, 1차 캐시에 있는 엔티티를 반환한다. 하지만 @Modifying의 clearAutomatically를 true로 변경해준다면, 벌크 연산 직 후 자동으로 영속성 컨텍스트를 clear 해준다.

 

그러면 조회를 실행하면 1차 캐시에 해당 엔티티가 존재하지 않기 때문에 DB 조회 쿼리를 실행하게 된다. 이렇게 함으로써 데이터 동기화 문제를 해결할 수 있다.

벌크 연산은 1차 캐시를 포함한 영속성 컨텍스트를 무시하고 바로 Query를 실행하기 때문에 영속성 컨텍스트는 데이터 변경을 알 수 없다. 즉, 벌크 연산을 실행할 대 1차 캐시(영속성 컨텍스트)와 DB의 데이터 싱크가 맞지 않게 되는 것이다.