1. 벌크 연산이란?
벌크 연산(Bulk Operation)이란, 한 번의 SQL 쿼리로 여러 건의 데이터를 일괄 수정 또는 삭제하는 작업을 말한다.
이는 개별 엔티티를 하나씩 수정하거나 삭제하는 것보다 훨씬 빠르고 효율적이다.
특징 | 설명 |
목적 | 대량 데이터 일괄 처리 |
성능 | 단건 처리보다 뛰어남 |
JPA에서 | JPQL의 update, delete로 수행 |
QueryDSL에서 | queryFactory.update(), queryFactory.delete() 사용 |
2. QueryDSL 벌크 수정 (Update)
예시 1: 조건에 따라 특정 값으로 일괄 수정
long count = queryFactory
.update(member)
.set(member.username, "비회원")
.where(member.age.lt(28))
.execute();
설명 | 내용 |
수정 대상 | username 필드를 "비회원"으로 |
조건 | age < 28인 멤버만 |
반환값 | 영향을 받은 row 수 (long) |
예시 2: 숫자 필드 계산식으로 수정
queryFactory
.update(member)
.set(member.age, member.age.add(1)) // 나이 + 1
.execute();
.set(member.age, member.age.multiply(2)) // 나이 * 2
특징 | 내용 |
연산 적용 | add(), multiply() 등 지원 |
SQL로 변환 | UPDATE member SET age = age + 1 등 |
3. QueryDSL 벌크 삭제 (Delete)
long count = queryFactory
.delete(member)
.where(member.age.gt(18))
.execute();
설명 | 내용 |
삭제 대상 | age > 18인 모든 member |
동작 방식 | DB에 직접 DELETE 쿼리 실행 |
대안 | deleteFrom()도 사용 가능 |
4. 주의사항: 영속성 컨텍스트와의 관계
* 벌크 연산은 영속성 컨텍스트를 무시한다
예시
em.persist(new Member("user1", 25)); // 영속 상태
queryFactory.update(member)
.set(member.username, "비회원")
.where(member.age.lt(28))
.execute();
이후에 em.find() 또는 user1.getUsername()을 출력하면 "비회원"이 아니라 기존 값 "user1"이 반환된다.
해결책: flush() + clear()
em.flush();
em.clear();
- flush(): 변경사항을 DB에 반영
- clear(): 영속성 컨텍스트 초기화
- 이후 조회 시 실제 DB 상태 기준으로 동작
5. 추가로 알아야 할 개념
1. execute() vs fetch()
메서드 | 용도 | 반환값 |
execute() | update, delete, insert에서 사용 | 영향을 받은 row 수 (long) |
fetch() | select 쿼리 결과 조회 | 리스트 또는 단건 |
2. 벌크 연산 vs 일반 연산
항목 | 벌크 연산 | 일반 연산 |
대상 | 여러 건 (조건 기반) | 엔티티 단건 또는 반복 처리 |
성능 | 빠름 | 상대적으로 느림 |
컨텍스트 반영 | ❌ 무시 | ✅ 영속성 컨텍스트 자동 반영 |
후처리 | flush(), clear() 필요 | 별도 필요 없음 |
3. Spring Data JPA에서 벌크 연산
@Modifying(clearAutomatically = true)
@Query("update Member m set m.username = '비회원' where m.age < :age")
int bulkUpdate(@Param("age") int age);
- @Modifying → JPQL로 벌크 연산 허용
- clearAutomatically = true → 자동으로 컨텍스트 초기화
6. 정리
항목 | 설명 |
update() | 조건에 따라 여러 행 수정 |
delete() | 조건에 따라 여러 행 삭제 |
execute() | 벌크 연산 실행 및 결과 row 수 반환 |
주의 | 영속성 컨텍스트를 무시하므로 flush + clear 필수 |
숫자 연산 | .add(), .multiply() 등 사용 가능 |
장점 | 한 번의 쿼리로 대량 데이터 처리 → 성능 향상 |
단점 | 컨텍스트와의 불일치로 인해 혼동 발생 가능 |
반응형
'Backend > JPA' 카테고리의 다른 글
Spring Data JPA와 Querydsl을 활용한 페이징 처리 및 성능 최적화 (0) | 2025.04.11 |
---|---|
Querydsl - 사용자 정의 JPA 리포지토리 설계 및 구현 (0) | 2025.04.11 |
QueryDSL 동적 쿼리 - (BooleanBuilder, Where 다중 파라미터 방식) (0) | 2025.03.25 |
QueryDsl - 프로젝션을 DTO 결과로 반환하는 방법과 개념 (0) | 2025.03.17 |
JPA (Spring Data JPA) - Spring Boot 3+ QueryDSL 및 JPA 기본 설정, p6spy 로깅 방법 (0) | 2025.03.13 |