Named 쿼리와 벌크 연산에 대해 알아보자
@Entity
@NamedQuery(
name = "Member.findByUsername",
query="select m from Member m where m.username = :username")
public class Member {
...
}
List<Member> resultList =
em.createNamedQuery("Member.findByUsername", Member.class)
.setParameter("username", "회원1")
.getResultList();
Spring Data JPA에서의 Named 쿼리 -
@Query: 이름없는 Named 쿼리
알고보니 내가 프로젝트에서 JPQL을 사용하던 방식이 Named 쿼리였다!
- 재고가 10개 미만인 모든 상품의 가격을 10% 상승하려면?
- JPA 변경 감지 기능으로 실행하려면 너무 많은 SQL 실행
- 재고가 10개 미만인 상품을 리스트로 조회한다.
- 상품 엔티티의 가격을 10% 증가한다.
- 트랜잭션 커밋 시점에 변경감지가 동작한다.
- 변경된 데이터가 100건이라면 100번의 UPDATE SQL 실행
executeUpdate()의 결과는 영향받은 엔티티 수 반환String qlString = "update Product p " +
"set p.price = p.price * 1.1 " +
"where p.stockAmount < :stockAmount";
int resultCount = em.createQuery(qlString)
.setParameter("stockAmount", 10)
.executeUpdate();
// 벌크 연산을 먼저 실행하지 않고 영속성 컨텍스트에 기존 데이터가 그대로 남아있다면 아래와 같은 문제를 초래함
// 따라서 가장 먼저 실행하거나, em.clear()를 통해 영속성 컨텍스트를 초기화해주어야 함
Member member1 = new Member();
member1.setUsername("회원1");
member1.setAge(0);
member1.setTeam(teamA);
em.persist(member1);
Member member2 = new Member();
member2.setUsername("회원2");
member2.setAge(0);
member2.setTeam(teamA);
em.persist(member2);
int resultCount = em.createQuery("update Member m set m.age = 20")
.executeUpdate();
Member findMember = em.find(Member.class, member1.getId());
System.out.println("findMember = " + findMember.getAge()); // findMember = 0이 출력됨