스프링 공부/JPA

[JPA] 28. Re.Zero : JPQL : 뻘크업(연)산

장아장 2023. 1. 19. 19:39

뻘컵뻘컵!!

벌크 연산

쉽게 생각하면 sql의 update, delete문을 일컫는다. 

Row 하나를 골라 실행하는 것이 아닌, 전체를 기준으로 실행시키는 방식이다. 

 

이를 JPA에서 기본 제공하는 변경 감지로 실행하려면

  1. 변경해야할 대상들을 쿼리문으로 가져온다. 
  2. 가져온 엔티티의 값을 변경시킨다. 
  3. 변경될 때 마다 변경 감지가 발생해 바꿀 때 마다 update문이 발생한다.
  4. 쓸데없이 쿼리를 많이 쓰게 된다.(이것도 N+1처럼 쿼리 하나 후에 N번의 쿼리를 또 처리하는 모습이다)

 

이럴 때 .executeUpdate를 실행하면 한번에 테이블 단위로 조작이 가능하다. 

 

이런식으로 나이를 1~100으로 만들어둔 후, 모든 멤버의 나이를 20으로 update시키는 쿼리문을 날렸다. (벌크 연산)

이 후 나이가 20인 멤버를 셌을 때, 

100개가 전부 카운트되는 것을 확인할 수 있다.

 

이러한 벌크 연산은, 영속성 컨텍스트가 아닌 DB에 바로 들어간다. 

그래서, 벌크 연산을 해도, 영속성 컨텍스트가 남아있으면 벌크 연산으로 바뀌지 않은 값을 조회해온다. 

 

이에 대한 해결책은, 

  1. 벌크 연산을 먼저 수행하거나
  2. 벌크 연산 후 영속성 컨텍스트를 초기화시킨다.

의 방법중에 하나를 채택해야 한다. 

 

개인적으로는 벌크 연산 뒤에 em.clear를 하나 붙여두는게 더 나은 방법이지 않을 까 싶다. 

특히 사용자가 많을 경우에는, 그 사이에 서버를 내리지 않는 한 계속해서 요청과 응답이 이루어지는데, 

이 사이에 벌크 연산이 있으면 먼저 수행한다는 말을 맞추기가 힘들 것 같다.