
벌크 연산이란 한 번의 SQL 쿼리로 여러 개의 데이터를 수정하거나 삭제하는 기능이다.
특정 조건인 엔티티에 대해서 값을 동시에 변경할 때, 변경 감지를 사용하면 update sql이 너무 많이 실행될 수 있기 때문에, 벌크 연산을 사용하는 것이 좋다.
String qlString = "update Product p " +
"set p.price = p.price * 1.1 " +
"where p.stockAmount < :stockAmount";
int resultCount = em.createQuery(qlString)
.setParameter("stockAmount", 10)
.executeUpdate(); //영향받은 엔티티 수 반환
executeUpdate()를 사용하여 벌크 연산을 실행하며, 영향을 받은 엔티티 수를 반환한다.@Modifying
@Query("update Member m set m.age = m.age + 1 where m.age >= :age")
int bulkAgePlus(@Param("age") int age);
@Modifying 어노테이션을 사용하여 데이터 변경 쿼리임을 명시한다.@Modifying(clearAutomatically = true) (기본값 false) 옵션을 사용하면, 벌크 연산 후 영속성 컨텍스트를 자동으로 초기화하여 데이터 불일치 문제를 방지할 수 있다. 벌크 연산 후 다시 조회해야 하는 경우에 이 옵션을 설정하자.벌크 연산은 영속성 컨텍스트를 무시하고 데이터베이스에 바로 쿼리를 날린다. (flush는 commit이나, 쿼리가 나갈 때 호출된다. 따라서 벌크 연산 쿼리가 나갈 때 flush가 되는 것이다.)
→ 영속성 컨텍스트에 값이 있는 경우, 벌크 연산을 하고 난 후 초기화를 하지 않으면, 영속성 컨텍스트에 있는 값은 최신 db 상태가 아니라서 데이터 불일치 문제가 발생할 수 있다.
해결 방법