벌크성 수정 쿼리는 예를 들어 회사 전체 직원의 연봉을 10% 인상한다고 가정할 때 전체 직원의 연봉을 한번에 수정하는 것을 벌크성 수정(벌크성 삭제도 가능)이라고 한다.
@Modifying(clearAutomatically = true)
@Query("update Member m set m.age = m.age + 1 where m.age >= :age")
int bulkAgePlus(@Param("age") int age);
벌크성 수정, 삭제 쿼리는 @Modifying
어노테이션을 지정해줘야 한다. 지정하지 않을 경우 getResultList()나 getSingleResult()를 호출해 rg.hibernate.hql.internal.QueryExecutionRequestException: Not supported for DML operations
예외가 발생한다. 그렇기 때문에 @Modifying
어노테이션을 사용해 executeUpdate()
를 실행시키게 해야 한다.
@Test
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);
List<Member> result = memberRepository.findByUsername("member5");
Member member5 = result.get(0);
System.out.println("member5 = " + member5);
// then
assertThat(resultCount).isEqualTo(3);
}
Jpa는 영속성 컨텍스트 관리하에 DB에 반영된다. 하지만 벌크성 수정, 삭제 쿼리는 영속성 컨텍스트를 무시하고 바로 DB에 반영되어 버린다.
member5 = Member(id=5, username=member5, age=40)
테스트 코드를 실행할 경우 DB에는 member5가 41로 수정 됐지만 영속성 컨텍스트에 있는 member5는 그대로 40이 출력된다. 그렇기 때문에 영속성 컨텍스트를 비워주는 작업을 진행해줘야 한다.
@Modifying(clearAutomatically = true)
@Modefying
어노테이션에 clearAutomatically를 true로 설정하면 entityManager.clear()와 같은 동작을 수행한다. (영속성 컨텍스트를 비움)