벌크 연산
벌크 연산
왜 사용할까?
만약 재고가 10개 미만인 모든 상품의 가격을 10% 상승한다고 해보자.
그러면 JPA는 더티체킹을 통해 10개의 SQL문을 내보낼 것이다.
그러나 10개가 아니고 100만건이라면? 너무 많은 SQL로 인해서 성능 이슈가
생길 것이다. 이런 문제를 해결하기 위해서는 벌크 연산을 사용해야 한다.
• 애플리케이션 로딩 시점에 쿼리를 검증
특징
• 쿼리 한 번으로 여러 테이블의 로우를 변경
• executeUpdate()
메소드는 영향받은 엔티티의 수를 반환한다.
• UPDATE, DELETE 지원
예시 코드
int resultCount = em.createQuery("update Member m set m.age=20")
.executeUpdate();
주의 사항
벌크 연산은 영속성 컨텍스트를 무시 하고 데이터베이스에 직접 쿼리한다.
따라서 이 주위 사항을 피하기 위해선 아래의 해결책 중 하나를 따르면 된다.
• 벌크 연산을 제일 먼저한다.
• 중간에 벌크 연산을 수행 했다면 영속성 컨텍스트를 초기화해 줘야 한다.
영속성 컨텍스트를 초기화 해주지 않으면 아래와 같이 데이터 정합성이
맞지 않게 된다.
Member member1 = new Member("member1", 20);
em.persist(member1);
int resultCount = em.createQuery("update Member m set m.age=25")
.executeUpdate();
System.out.println(member1.getAge()); // 20
위 코드의 결과를 보면 어플리케이션에서는 member1의 나이가 변하지 않았다.
하지만 DB를 조회해보면 나이가 20살에서 25살로 변했다.
ID | AGE | USERNAME |
---|---|---|
1 | 25 | member1 |
이번에는 영속성 컨텍스트를 초기화하고 진행해보겠다.
Member member1 = new Member("member1", 20);
em.persist(member1);
//=> 이 시점에 flush() 호출
int resultCount = em.createQuery("update Member m set m.age=25")
.executeUpdate();
/* 영속성 컨텍스트 초기화 */
em.clear();
Member findMember = em.find(Member.class, member1.getId());
System.out.println(findMember.getAge()); // 25
ID | AGE | USERNAME |
---|---|---|
1 | 25 | member1 |
DB데이터와 어플리케이션 데이터가 일치함을 확인할 수 있다.