-
재고가 10개 미만인 모든 상품의 가격을 10% 상승 시키자는 가정이 있다고 하자.
JPA의 update는 변경 감지 기능이 가장 좋다.
1. 재고가 10개 미만인 상품을 리스트로 조회
2. 상품 엔티티의 가격을 10% 증가
3. 트랜잭션 커밋 시점에 변경감지가 동작
하지만 이런 과정을 거치며 변경된 데이터가 100건이라면 100번의 UPDATE SQL이 실행되어야 하니까 효율적이지 않다.
하나를 변경할 때에는 변경 감지가 좋지만 한 번에 여러 건을 변경할 때에는 벌크 연산이 좋다.
벌크 연산 예제
쿼리 한 번으로 여러 테이블 로우를 변경한다.
int resultCount = em.createQuery("update Member m set m.age = 20") .executeUpdate(); System.out.println("resultCount = " + resultCount); // 변경된 member의 개수
간단히 변경할 수 있는데, update 쿼리를 한 다음에 .excuteUpdate()를 붙여주면 된다. 반환 값은 변경된 요소들의 개수를 반환해준다.
벌크 연산의 주의점
벌크 연산은 영속성 컨텍스트를 무시하고 데이터베이스에 직접 쿼리
해결점
1. 벌크 연산을 먼저 실행
2. 벌크 연산 수행 후 영속성 컨텍스트 초기화
둘 중 하나를 선택해서 사용하면 된다.
Member member1 = new Member(); member1.setUsername("member1"); member1.setTeam(teamA); em.persist(member1); Member member2 = new Member(); member2.setUsername("member2"); member2.setTeam(teamA); em.persist(member2); Member member3 = new Member(); member3.setUsername("member3"); member3.setTeam(teamA); em.persist(member3); 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 = " + findMember.getAge());
findMember를 가져와서 조회를 해도 20살이 아니라 기본 값인 0살로 조회가 된다.
왜냐하면 영속성 컨텍스트에는 0살로 저장되었는데, 벌크 연산은 영속성 컨텍스트를 무시하고 db에 바로 반영시켜주기 때문이다.
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 = " + findMember.getAge());
em.clear()로 영속성 컨텍스트를 초기화하면 db에서 새로 조회하기 때문에 db에 있는 20살이 나오게 된다.
'JPA > JPQL' 카테고리의 다른 글
Named 쿼리 (0) 2023.08.09 엔티티를 직접 사용하기 (0) 2023.08.09 페치 조인의 한계 (0) 2023.08.09 페치 조인(fetch join) (0) 2023.08.09 경로 표현식 (0) 2023.08.09