본문 바로가기
  • 실행력이 모든걸 결정한다
Spring 사전 준비/JPA Hibernate

[JPA] JPQL 최적화

by 김코더 김주역 2022. 8. 14.
반응형

1. 벌크 연산

1) 벌크 연산이란?

- 성능을 위해 엔티티를 한 번에 수정하거나 삭제하는 연산을 의미한다.

- UPDATE와 DELETE 모두 executeUpdate() 메소드를 사용하면 된다. INSERT 벌크 연산은 JPA 표준은 아니지만 Hibernate에서는 지원한다.

int resultCount = em.createQuery("[UPDATE/DELETE SQL]")
    .setParameter("price", 200)
    .executeUpdate(); // 영향 받은 엔티티의 건수를 반환

 

- QueryDSL을 이용하는 방법은 https://kimcoder.tistory.com/495의 [11.배치 쿼리]를 참고하자.

- 벌크 연산은 영속성 컨텍스트를 무시하고 DB에 직접 쿼리한다.

 

2) 일관성 문제 해결

- 영속성 컨텍스트를 무시하고 DB에 직접 쿼리하게 되면 일관성 문제가 발생할 수 있다. 변경된 내용이 DB에만 반영되고 영속성 컨텍스트에는 기존 내용이 그대로 남아있게 되는 것이다. 이러한 문제를 해결하기 위한 3가지 방법이 있다.

  • EntityManager.refresh() 사용 : DB로부터 엔티티를 다시 조회한다.
  • 벌크 연산을 먼저 실행
  • 벌크 연산 수행 후 영속성 컨텍스트 초기화 : EntityManager로 엔티티 조회를 시도하면 가장 먼저 영속성 컨텍스트에서 엔티티를 찾아보고 엔티티를 찾지 못했다면 DB를 조회한다는 특징을 이용한 방법이다. 영속성 컨텍스트를 초기화해두면 엔티티를 조회할 때 DB에 있는 데이터를 불러오게 된다.

 

 

2. EntityManager.find() vs JPQL

- EntityManager.find()는 영속성 컨텍스트를 DB보다 먼저 조회한다. 영속성 컨텍스트에서 엔티티를 찾았다면 DB를 조회하지 않고 영속성 컨텍스트에 있던 엔티티를 반환한다.

- JPQL은 DB를 영속성 컨텍스트보다 먼저 조회한다. 영속성 컨텍스트에 같은 엔티티가 있다면 DB로 조회한 엔티티는 버리고 영속성 컨텍스트에 있던 엔티티를 반환한다.

=> 전자가 성능상 이점이 있다.

 

 

3. FlushMode

- 기본적으로 commit이나 쿼리 실행 직전에 자동으로 flush()가 호출된다. JPQL 쿼리의 경우에는 일관성 문제를 방지하기 위해 기본적으로 flush()가 미리 호출되는 것이다.

- EntityManager.setFlushMode()로 flush 모드를 지정할 수 있으며, 인자로 javax.persistence.FlushModeType을 선택할 수 있다. 제공되는 옵션은 아래 내용을 참고하자.

FlushModeType.AUTO // (기본값) Commit 또는 JPQL쿼리 실행 시에 flush
FlushModeType.COMMIT // Commit할 때만 flush

참고로, Query 객체에도 setFlushMode()를 사용할 수 있다. 특정 쿼리에서만 다른 flush 모드를 사용하고 싶다면 Query 객체에 flush 모드를 지정하면 된다. Flush 모드는 EntityManager 설정보다 Query 설정이 우선권을 가진다.

em.setFlushMode(FlushModeType.COMMIT); // 2순위

Member member = em.createQuery(...)
    .setFlushMode(FlushModeType.AUTO) // 1순위
    .getSingleResult();

- Flush 모드는 웬만하면 기본값으로 충분하지만, 성능 최적화시에 flush 모드를 FlushModeType.COMMIT으로 바꿔야 할 수도 있다. Flush가 너무 자주 일어나는 상황이라면 flush 횟수를 줄이기 위해 COMMIT 모드를 고려해볼만 하다. 

- JPA와 달리 비 ORM 기술은 보통은 캐시를 적용하지 않기 때문에, 비 ORM 기술과 트랜잭션을 공유하는 경우에는 비 ORM 기술의 쿼리를 실행하기 직전에 flush()를 호출해서 영속성 컨텍스트의 내용을 DB에 동기화해주는 것이 안전하다.

 

 

● 참고자료 : 자바 ORM 표준 JPA 프로그래밍

 

 

반응형

'Spring 사전 준비 > JPA Hibernate' 카테고리의 다른 글

[JPA] Spring Data JPA(2)  (0) 2022.08.20
[JPA] Spring Data JPA(1)  (0) 2022.08.19
[JPA] 스토어드 프로시저  (0) 2022.08.14
[JPA] 네이티브 SQL  (0) 2022.08.11
[JPA] QueryDSL  (0) 2022.08.10

댓글