벌크 연산
Last updated
Last updated
벌크 연산 : 영속성 컨텍스트를 무시하고 바로 DB에 데이터 업데이트한다!
JPA 변경 감지 기능으로 실행하려면 너무 많은 SQL 실행 ex) 재고가 10개 미만인 상품을 리스트로 조회 상품 엔티티의 가격을 10% 증가
트랜잭션 커밋 시점에 변경감지가 동작한다! => 변경된 데이터가 100건이라면 100번의 UPDATE SQL을 실행한다!
벌크 연산 예제
쿼리 한 번으로 여러 테이블 로우 변경(엔티티)
executeUpdate()의 결과는 영향받은 엔티티 수 반환. - UPDATE, DELETE 지원
INSERT(insert into .. select, 하이버네이트 지원)
아래 코드를 실행하면 벌크 연산이 실행되면서 flush가 자동으로 되면서 insert 쿼리문이 나간다! 그러므로 영속성 컨텍스트의 데이터들은 DB에 들어가고, 그 다음에 update 쿼리문이 실행된다! 이 update문은 DB에 바로 업데이트된다!
(참고)flush가 되는 때
commit 시점
쿼리가 나갈 때
강제로 flush 호출
벌크 연산 주의 벌크 연산은 영속성 컨텍스트를 무시하고 데이터베이스에 직접 쿼리
벌크 연산을 먼저 실행 : 영속성 컨텍스트에 저장하지 말고 벌크연산만 실행한다! => 영속성 컨텍스트에 아무것도 없기 때문에 문제 없다!
벌크 연산 수행 후 영속성 컨텍스트 초기화(권장) => 벌크 연산 또한 flush는 된다(쿼리가 나오기 때문에!) 벌크 연산 수행 후 영속성 컨텍스트 초기화해야하는 이유 => 예전에 조회한 데이터(5000)가 영속성 컨텍스트에 있는데 벌크연산(6000)하고나면 DB에는 6000이 있고 영속성 컨텍스트에는 여전히 5000으로 있다. 그렇기 때문에 데이터 정합성을 위 벌크 연산하고 나면 DB 업데이트하면 영속성 컨텍스트는 초기화한다!
벌크 연산 update문은 DB에만 반영된 것이므로 값을 조회하면 영속성 컨텍스트(여전히 '0')에 있는 값을 가져온다!!!
따라서 em.clear()로 영속성 컨텍스트를 초기화한 후 em.find()로 DB에서 값을 새로 가져온다 =>벌크 연산으로 DB에 업데이트된 값을 조회할 수 있다!⭐️⭐️⭐️⭐️⭐️
스프링 데이터 JPA에서는 @Modifying을 통해 벌크연산 후에 자동으로 영속성 컨텍스트를 초기화해준다!