본문 바로가기
[JAVA]/JPA

JPQL - 벌크 연산

by 황원용 2023. 5. 14.
728x90

재고가 10개 미만인 모든 상품의 가격을 10% 올리려면 어떻게 해야 할까?

  • JPA 변경 감지 기능으로 실행하려면 너무 많은 SQL이 실행될 것이다.
    • 1. 재고가 10개 미만인 상품을 리스트로 조회한다.
    • 2. 상품 엔티티의 가격을 10% 증가한다.
    • 3. 트랜잭션 커밋 시점에 변경 감지가 동작한다.
    • 변경된 데이터가 100건이라면 100번의 UPDATE SQL문이 실행될 것이다.

 

 

벌크 연산

  • 쿼리 한 번으로 여러 테이블의 로우(엔티티)를 변경한다.
  • executeUpdate()를 사용하여 연산할 수 있다.

 

// 모든 Member의 나이를 20살로 변경한다.
int resultCount = em.createQuery("update Member m set m.age = 20")
			.executeUpdate();
  • executeUpdate()의 결과는 벌크 연산으로 변경되거나 삭제되는 등 영향받은 엔티티 수를 반환한다.
  • UPDATE, DELETE를 지원한다.
  • JPA 스펙에는 없지만 하이버네이트를 쓰면 INSERT(insert into .. select, 하이버네이트 지원)에도 사용할 수 있다.

 

 

벌크 연산 사용시 주의할 점

  • 벌크 연산은 영속성 컨텍스트를 무시하고 데이터베이스에 직접 쿼리를 날린다.
  • 영속성 컨텍스트가 비었을 때 : 벌크 연산을 먼저 실행한다.
  • 영속성 컨텍스트에 데이터가 있을 때 : 벌크 연산 수행 후에 영속성 컨텍스트를 초기화한다.
    • EX) 벌크 연산으로 직원 연봉을 10% 인상시켰다.
    • 데이터베이스는 10% 인상된 연봉으로 업데이트되었지만 영속성 컨텍스트 안의 연봉 데이터는 인상 전 그대로이기 때문에 꼬인다. 따라서 초기화를 해야 한다.
double resultCount = em.createQuery("update Member m set m.salary = m.salary * 1.1") // 5000 * 1.1 = 5500
			.executeUpdate();
em.clear(); // 영속성 컨텍스트 초기화

Member findMember = em.find(Member.class, member1.getId());
System.out,println("findMember = " + findMember.getSalary());


// 출력
findMember = 5500.0;

 

 

 

@Modifying

@Modifying
@Query("update ~ set") // Spring Data JPA에서 @Modifying을 이용해 벌크 연산을 할 수 있다.

 

728x90