객체지향 쿼리 심화
벌크 연산
수백 개 이상의 엔티티를 수정하거나 삭제하는 경우 벌크 연산을 사용하면 빠르게 처리할 수 있다
예를 들어 재고가 10개 미만인 모든 상품의 가격을 10% 올리려면 다음과 같이 벌크 연산을 사용하면 된다
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();
벌크 연산은 executeUpdate() 메소드를 사용한다
이 메소드는 벌크 연산으로 영향을 받은 엔티티 건수를 반환한다
삭제도 같은 메소드를 사용한다
벌크 연산의 주의점
벌크 연산이 영속성 컨텍스트를 무시하고 데이터베이스에 직접 쿼리한다는 점을 주의해야 한다
-> 영속성 컨텍스트에 있는 값과 데이터베이스에 있는 값이 다를 수 있다
위와 같은 문제를 해결하는 방법은 다음과 같다
1. em.refresh() 사용
벌크 연산을 수행한 후 em.refresh()를 이용해 데이터베이스에서 엔티티를 다시 조회한다
2. 벌크 연산 먼저 실행
벌크 연산을 먼저 실행한 후 엔티티를 조회하도록 한다
3. 벌크 연산 수행 후 영속성 컨텍스트 초기화
벌크 연산을 수행한 직후 영속성 컨텍스트를 초기화해서 영속성 컨텍스트에 남아 있는 엔티티를 제거한다
가능하면 벌크 연산을 가장 먼저 수행하는 것이 좋고 상황에 따라 영속성 컨텍스트를 초기화하는 것도 필요하다
영속성 컨텍스트와 JPQL
쿼리 후 영속 상태인 것과 아닌 것
JPQL의 조회 대상은 엔티티, 임베디드 타입, 값 타입 같이 다양한 종류가 있는데,
JPQL로 엔티티를 조회하면 영속성 컨텍스트에서 관리되지만 그렇지 않은 경우에는 영속성 컨텍스트에서 관리되지 않는다
JPQL로 조회한 엔티와 영속성 컨텍스트
JPQL로 데이터베이스에서 조회한 엔티티가 이미 영속성 컨텍스트에 있는 경우,
데이터베이스에서 조회한 결과를 버리고 대신 영속성 컨텍스트에 있던 엔티티를 반환한다
데이터베이스에서 조회한 엔티티를 사용할 경우 영속성 컨텍스트에서 수정 중이던 데이터가 사라질 수 있으므로 위험하므로
영속성 컨텍스트에 있던 엔티티를 반환한다
즉, 영속성 컨텍스트는 영속 상태인 엔티티의 동일성을 보장한다
find() vs JPQL
em.find()는 엔티티를 영속성 컨텍스트에서 먼저 찾고 없으면 데이터베이스에서 찾는다
JPQL은 항상 데이터베이스에서 SQL을 실행해서 결과를 조회해 영속성 컨텍스트에 저장한다
이때 같은 엔티티가 이미 영속성 컨텍스트에 있다면 새로 검색한 엔티티를 버리고 기존의 엔티티를 반환한다
JPQL과 플러시 모드
플러시 모드 종류
- em.setFlushMode(FlushModeType.AUTO): 커밋 또는 쿼리 실행 시 플러시 (기본 값)
- em.setFlushMode(FlushModeType.COMMIT): 커밋 시에만 플러시
쿼리와 플러시 모드
JPQL은 영속성 컨텍스트에 있는 데이터를 고려하지 않고 데이터베이스에서 데이터를 조회한다
JPQL을 실행하기 전에 영속성 컨텍스트의 내용을 데이터베이스에 반영해야 한다
플러시 모드가 AUTO인 경우에는 JPQL 쿼리 실행 직전에 영속성 컨텍스트를 플러시 해 수정한 내용을 조회할 수 있다
플러시 모드가 COMMIT인 경우에는 쿼리 전 플러시 하지 않아 방금 수정한 데이터를 조회할 수 없다
- 직접 em.flush()를 호출하거나 Query 객체에 해당 쿼리만 플러시 모드를 AUTO로 설정해주면 된다
플러시 모드와 최적화
FlushModeType.COMMIT 모드는 잘못하면 데이터 무결성에 피해를 줄 수 있다는 단점이 있지만
플러시가 너무 자주 일어나는 상황에서는 플러시 횟수를 줄여 성능을 최적화할 수 있다는 장점이 있다
'스터디 > JPA' 카테고리의 다른 글
스프링 데이터 JPA - (2) (0) | 2025.02.20 |
---|---|
스프링 데이터 JPA - (1) (0) | 2025.02.20 |
객체지향 쿼리 언어 - (6) (0) | 2025.02.19 |
객체지향 쿼리 언어 - (5) (0) | 2025.02.18 |
객체지향 쿼리 언어 - (4) (0) | 2025.02.18 |