본문 바로가기

Spring Data

벌크 연산

재고가 10개 미만인 모든 상품의 가격을 10% 상승하려면?

JPA 변경 감지 기능으로 실행하려면 너무 많은 SQL 실행

  1. 재고가 10개 미만인 상품을 리스트로 조회한다.
  2. 상품 엔티티의 가격을 10% 증가한다.
  3. 트랜잭션 커밋 시점에 변경 감지가 동작한다.

변경된 데이터가 100건이라면 100번의 update SQL 실행

벌크 연산 주의

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

만약 어떤 그룹의 연봉을 4000만원에서 5000만 원으로 수정하는 벌크 연산을 날리게 되면 데이터베이스에 직접 쿼리 하여 값이 수정된다. 하지만 영속성 컨텍스트를 무시했기 때문에 영속성 컨텍스트에는 아직 4000만 원으로 설정되어 있음.

 

Member member1 = new Member();
member1.setUsername("회원1");
member1.setAge(0);
em.persist(member1);	// 영속성 컨텍스트 등록

Member member2 = new Member();
member2.setUsername("회원2");
member2.setAge(0);
em.persist(member1);	// 영속성 컨텍스트 등록

int resultCount = em.createQuery("update Member m set m.age = 20").executeUpdate();

// 쿼리 발생안됨 영속성 컨텍스트에 이미 존재하기 때문에.
Member findMember = em.find(Member.class, member1.getId());

System.out.println("findMember.age = " + findMember.getAge()); 
// 실행결과
// findMember.age = 0

// DB에는 20으로 Update 되었지만 영속성 컨텍스트에서 수정되지 않았기 때문에..

해결방법

  • 벌크 연산을 먼저 실행
  • 벌크 연산 수행 후 영속성 컨텍스트 초기화

 

Member member1 = new Member();
member1.setUsername("회원1");
member1.setAge(0);
em.persist(member1);	// 영속성 컨텍스트 등록

Member member2 = new Member();
member2.setUsername("회원2");
member2.setAge(0);
em.persist(member1);	// 영속성 컨텍스트 등록

int resultCount = em.createQuery("update Member m set m.age = 20").executeUpdate();

// 영속성 컨텍스트 초기화
em.clear();

// 영속성 컨텍스트에 없기 때문에 새롭게 조회해 온다.
Member findMember = em.find(Member.class, member1.getId());

System.out.println("findMember.age = " + findMember.getAge()); 
// 실행결과
// findMember.age = 20

'Spring Data' 카테고리의 다른 글

JPQL 중급 문법 - 페치조인2  (0) 2021.08.09
JPQL 중급 문법 - 페치 조인1  (0) 2021.08.09
JPQL 중급 문법 - 경로표현식  (0) 2021.08.09
JPQL 기본 문법  (0) 2021.08.09
값 타입 #9  (0) 2021.07.26