벌크 연산

  • 벌크 연산 : 영속성 컨텍스트를 무시하고 바로 DB에 데이터 업데이트한다!

  • JPA 변경 감지 기능으로 실행하려면 너무 많은 SQL 실행 ex) 재고가 10개 미만인 상품을 리스트로 조회 상품 엔티티의 가격을 10% 증가

  • 트랜잭션 커밋 시점에 변경감지가 동작한다! => 변경된 데이터가 100건이라면 100번의 UPDATE SQL을 실행한다!

벌크 연산 예제

  • 쿼리 한 번으로 여러 테이블 로우 변경(엔티티)

  • executeUpdate()의 결과는 영향받은 엔티티 수 반환. - UPDATE, DELETE 지원

  • INSERT(insert into .. select, 하이버네이트 지원)

아래 코드를 실행하면 벌크 연산이 실행되면서 flush가 자동으로 되면서 insert 쿼리문이 나간다! 그러므로 영속성 컨텍스트의 데이터들은 DB에 들어가고, 그 다음에 update 쿼리문이 실행된다! 이 update문은 DB에 바로 업데이트된다!

(참고)flush가 되는 때

  1. commit 시점

  2. 쿼리가 나갈 때

  3. 강제로 flush 호출

int resultCount = em.createQuery("update Member m set m.age = 20")
        .executeUpdate();
System.out.println("resultCount = " + resultCount);
age가 모두 20으로 된 모습

벌크 연산 주의 벌크 연산은 영속성 컨텍스트를 무시하고 데이터베이스에 직접 쿼리

  • 벌크 연산을 먼저 실행 : 영속성 컨텍스트에 저장하지 말고 벌크연산만 실행한다! => 영속성 컨텍스트에 아무것도 없기 때문에 문제 없다!

  • 벌크 연산 수행 후 영속성 컨텍스트 초기화(권장) => 벌크 연산 또한 flush는 된다(쿼리가 나오기 때문에!) 벌크 연산 수행 후 영속성 컨텍스트 초기화해야하는 이유 => 예전에 조회한 데이터(5000)가 영속성 컨텍스트에 있는데 벌크연산(6000)하고나면 DB에는 6000이 있고 영속성 컨텍스트에는 여전히 5000으로 있다. 그렇기 때문에 데이터 정합성을 위 벌크 연산하고 나면 DB 업데이트하면 영속성 컨텍스트는 초기화한다!

벌크 연산 update문은 DB에만 반영된 것이므로 값을 조회하면 영속성 컨텍스트(여전히 '0')에 있는 값을 가져온다!!!

따라서 em.clear()로 영속성 컨텍스트를 초기화한 후 em.find()로 DB에서 값을 새로 가져온다 =>벌크 연산으로 DB에 업데이트된 값을 조회할 수 있다!⭐️⭐️⭐️⭐️⭐️

스프링 데이터 JPA에서는 @Modifying을 통해 벌크연산 후에 자동으로 영속성 컨텍스트를 초기화해준다!

Last updated

Was this helpful?