JPA는 보통 더티체킹을 이용해서 엔티티 한 개씩 데이터를 변경한다. 그런데 한번에 여러개의 데이터를 업데이트 할때 사용한다.
회원의 나이를 한번에 변경하는 쿼리
public int bulkAgePlus(int age) {
return em.createQuery("update Member m set m.age = m.age + 1 where m.age >= :age")
.setParameter("age", age)
.executeUpdate();
}
@Test
public void bulkUpdate() {
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));
int resultCount = memberRepository.bulkAgePlus(20);
assertThat(resultCount).isEqualTo(3);
}
@Modifying
@Query("update Member m set m.age = m.age + 1 where m.age >= :age")
int bulkAgePlus(@Param("age") int age);
@Modifying 어노테이션을 꼭해야 된다.
만약 빼면
여기 까지는 쉽다. 그러나 JPA에서 이러한 업데이트를 할 때는 조심해야 한다.
벌크 연산은 영속성 컨텍스트를 모조리 무시한다.
@Test
public void bulkUpdate() {
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));
int resultCount = memberRepository.bulkAgePlus(20);
assertThat(resultCount).isEqualTo(3);
Optional<Member> findMember = memberRepository.findOptionalByUsername("member5");
assertThat(findMember.get().getAge()).isEqualTo(40);
}