반응형
JPA 게시글은 대부분 인프런의 김영한님의 강의인 '자바 ORM 표준 JPA 프로그래밍' 기반으로 내용을 정리했습니다.
벌크 연산
- 벌크 연산 : 일반적으로 잘 알고있는 SQL의 UPDTAE, DELETE
- 재고가 10개 미만인 모든 상품의 가격을 10% 상승하려면?
- JPA 변경 감지 기능으로 실행하려면 너무 많은 SQL 실행
- 재고가 10개 미만인 상품을 리스트로 조회
- 상품 엔티티의 가격을 10% 증가
- 트랜잭션 커밋 시점에 변경감지 동작
- 변경된 데이터가 100건이라면 100번의 UPDATE SQL이 실행
예제
- 쿼리 한 번으로 여러 테이블 로우를 변경(엔티티)
- executeUpdate()의 결과는 영향받은 엔티티 수 반환
- UPDATE, DELETE 지원
- INSERT(insert into ...select, 하이버네이트 지원)
- 모든 회원의 나이를 20살로 변경
int resultCount = em.createQuery("update Member m set m.age = 20")
.executeUpdate();
System.out.println("resultCount = " + resultCount);
Hibernate:
/* update
Member m
set
m.age = 20 */ update
Member
set
age=20
resultCount = 3
벌크 연산 주의점
- 벌크 연산은 영속성 컨텍스트를 무시하고 데이터베이스에 직접 쿼리 한다.
- 해결방법(둘 중에 하나 선택)
- 벌크 연산을 먼저 실행하거나
- 벌크 연산 수행 후 영속성 컨텍스트 초기화
Team teamA = new Team();
teamA.setName("팀A");
em.persist(teamA);
Team teamB = new Team();
teamB.setName("팀B");
em.persist(teamB);
Member member = new Member();
member.setUsername("회원1");
member.setTeam(teamA);
em.persist(member);
Member member2 = new Member();
member2.setUsername("회원2");
member2.setTeam(teamA);
em.persist(member2);
Member member3 = new Member();
member3.setUsername("회원3");
member3.setTeam(teamB);
em.persist(member3);
// em.flush();
// em.clear();
int resultCount = em.createQuery("update Member m set m.age = 20")
.executeUpdate();
System.out.println("resultCount = " + resultCount);
System.out.println("member.getAge() = " + member.getAge());
System.out.println("member2.getAge() = " + member2.getAge());
System.out.println("member3.getAge() = " + member3.getAge());
쿼리문 위에 영속성 컨텍스트를 초기화시키는 코드를 주석처리한다. 물론 flush야 쿼리가 실행되면 자동적으로 flush가 되긴하는데 문제는 clear이다. clear가 없는 경우 영속성 컨텍스트에는 나이가 20살로 변경되지 않고, 그대로 초기값인 0이 남아있다.
resultCount = 3
member.getAge() = 0
member2.getAge() = 0
member3.getAge() = 0
그러니 영속성 컨텍스트를 초기화해서 값을 불러올 필요가 있다.
int resultCount = em.createQuery("update Member m set m.age = 20")
.executeUpdate();
em.clear();
Member findMember = em.find(Member.class, member.getId());
System.out.println("findMember = " + findMember.getAge());
이런 식으로 벌크 연산 후 영속성 컨텍스트를 초기화시켜야 한다.
반응형