벌크 연산은 데이터를 한번에 수정하는 것을 의미한다.
벌크 연산은 1차 캐시를 거치지 않고 DB로 바로 접근하여 SQL을 실행하여 값을 수정한다.
따라서, 1차 캐시를 반드시 초기화 해야 한다. 1차 캐시를 초기화하지 않으면 벌크 연산으로 인해 수정된 DB 데이터와 1차 캐시에 있는 데이터의 정합성이 깨지게 된다.
순수 JPA를 사용하여 벌크 연산하기
@Repository
public class MemberJpaRepository {
public int bulkAgePlus(int age) {
return entityManager.createQuery(
"update Member m set m.age = m.age + 1 where m.age >= :age"
)
.setParameter("age", age)
.executeUpdate();
}
}
// MemberJpaRepositoryTest.java
@Test
public void bulkUpdate() {
memberJpaRepository.save(new Member("member1", 10));
memberJpaRepository.save(new Member("member3", 19));
memberJpaRepository.save(new Member("member3", 20));
memberJpaRepository.save(new Member("member4", 21));
memberJpaRepository.save(new Member("member5", 40));
int resultCount = memberJpaRepository.bulkAgePlus(20);
em.flush(); // 쓰기 지연 SQL 저장소에 남은 쿼리들을 실행한다.
em.clear(); // DB와의 정합성을 위해 영속성 컨텍스트를 초기화한다.
assertThat(resultCount).isEqualTo(3);
}
em.flush(), em.clear() 작업을 통해 영속성 컨텍스트를 깔끔하게 초기화함으로써 데이터의 정합성을 일치시켰다.
Spring Data JPA를 사용하여 벌크 연산하기
public interface MemberRepository extends JpaRepository<Member, Long> {
@Modifying(clearAutomatically = true)
@Query("update Member m set m.age = m.age + 1 where m.age >= :age")
int bulkAgePlus(@Param("age") int age);
}
Spring Data JPA에서는 @Modifying 어노테이션의 clearAutomatically 속성을 true로 설정하면 DB와의 정합성을 맞추기 위해 영속성 컨텍스트를 초기화한다.
결론
벌크 연산을 할 때는 DB의 정합성을 맞추기 위해 영속성 컨텍스트를 초기화하는 작업을 반드시 진행하자!