개요
- 벌크 연산 UPDATE, DELETE 를 사용해보자.
벌크 연산
- 여러 건(대량의 데이터)을 한 번에 수정하거나 삭제하는 연산
- 쿼리 한 번으로 여러 테이블 로우 변경한다.
- 결과는 영향받은 엔티티 수(long)를 반환한다.
변경 감지(Drity Checking)로 처리하면 안될까?
- 트랜잭션 내에서 엔티티의 데이터 변경이 일어나면 자동으로 변경 쿼리가 생성된다.
- 하지만 이 **변경 감지(Drity Checking)**는 개별 엔티티 건건으로 발생된다.
- 그러므로 여러 데이터 변경을 변경 감지를 통해 실행하려면 너무 많은 SQL이 실행된다.
벌크 연산 주의
- 벌크 연산은 영속성 컨텍스트를 무시하고 데이터베이스에 직접 쿼리를 날린다.
- DB 는 변경이 일어나지만 이미 영속성 컨텍스트에 있는 데이터는 변경이 일어나지 않는다.
- 데이터 정합성이 맞지 않을 수 있다.
- 그렇기 때문에 배치 쿼리를 실행하고 나면 영속성 컨텍스트를 초기화 하는 것이 안전하다.
- 캐시를 사용하는 추가 로직이 있다면 캐시를 직접 갱신할 필요가 있다.
- 벌크 연산 수행 후 영속성 컨텍스트 초기화(em.clear)
쿼리 한번으로 대량 데이터 수정 및 삭제
/**
* 멤버 나이가 28 보다 작다면 멤버 이름을 "비회원" 으로 변경
*/
@Test
void bulkUpdate() {
//given
//when
long count = jpaQueryFactory
.update(member)
.set(member.userName, "비화원")
.where(member.age.lt(28))
.execute();
em.clear(); // 영속성 컨텍스트 초기화
//then
List<Member> result = jpaQueryFactory
.selectFrom(member)
.fetch();
for (Member findMember : result) {
System.out.println("findMember = " + findMember);
}
}
@Test
void bulkDelete() {
//given
//when
long count = jpaQueryFactory
.delete(member)
.where(member.age.gt(18))
.execute();
//then
}
기존 숫자에 2 더하기