JPA는 더티 체킹을 통해 데이터 업데이트 쿼리가 자동으로 날아가도록 할 수 있지만, 더티 체킹은 한번에 업데이트를 하는게 아니라 하나씩 업데이트 쿼리가 진행되기 때문에 많은 데이터의 업데이트를 진행할 때는 성능이 떨어질 수 있다. 그렇기 때문에 여러 데이터를 한번에 업데이트 시키는 벌크성 수정 쿼리를 이용해야 한다.
@Modifying
@Query("update Member m set m.age = m.age + 1 where m.age >= :age")
int bulkAgePlus(@Param("age") int age);
벌크성 수정,삭제 쿼리는 @Modifying
어노테이션을 사용하지 않으면 예외가 발생하므로 필수로 사용해야 한다.
@Test
public void bulkUpdate() throws Exception {
//given
memberRepository.save(new Member("member1", 10));
memberRepository.save(new Member("member2", 19));
memberRepository.save(new Member("member3", 20));
memberRepository.save(new Member("member4", 21));
memberRepository.save(new Member("member5", 40));
//when
int resultCount = memberRepository.bulkAgePlus(20);
//then
Member findMember = memberRepository.findByUsername("member5");
System.out.println("findMember.getAge = " + findMember.getAge());
}
위 예제를 사용했을 때 우리는 41이라는 결과 값을 기대하지만 실제로는 40이 출력된다. 실제 데이터베이스를 확인해 보면 41이 저장되어 있는 것을 확인할 수 있는데, 이는 벌크성 수정 쿼리가 영속성 컨텍스트를 거치지 않고 진행되기 때문이다.
그렇기 때문에 벌크성 수정 쿼리를 사용하고 나서는 꼭 영속성 컨텍스트를 clear해줘야 한다.
또는 @Modifying(clearAutomatically = true)
옵션 값을 사용하는 것이 더욱 편리하므로 알아두는 것이 좋을것이다.