JPA

영속성 컨텍스트 vs JPQL

iksadnorth 2023. 9. 6. 13:17

해당 게시물은 책 '자바 ORM 표준 프로그래밍'을 읽고 작성했습니다.

👣 개요

JPQL은 영속성 컨텍스트에서 미리 조회하고 DB에 쿼리를 보내지 않고
DB에 쿼리를 먼저 보낸 후에 영속성 컨텍스트를 재정비한다.

JPQL의 경우, 영속성 컨텍스트를 활용하지 않기 때문에 
비교적 성능이 떨어질 수 있기 때문에 되도록 JPQL보다 
find()와 같은 메서드를 사용하는 것이 좋다.

하지만, 통계 쿼리와 같은 복잡한 쿼리를 보내는 것에 영속성 컨텍스트를 활용하기란
어려움이 많기에 JPQL을 사용할 수 밖에 없다.

영속성 컨텍스트를 이용한 조회.
JPQL을 이용한 조회

 

👣 플러시 모드와 최적화

원래 JPQL을 실행하면 Flush Mode가 FlushModeType.AUTO로 되어 있기 때문에 
영속성 컨텍스트와 DB 사이의 동기화를 유지할 수 있다.

FlushModeType.AUTO란, JPQL 쿼리를 DB로 보내고 결과를 받아올 때마다 
영속성 컨텍스트를 Flush하는 것을 의미한다.
동기화를 위해선 당연한 일처럼 보이지만 만약 1개의 Transcation에서 100개의 JPQL 쿼리가 날아가면
100번의 동기화가 일어나고 이는 불필요한 연산을 잡아먹는다.

만약 Transaction 내에서 JPQL만 활용한다고 가정한다면 굳이 영속성 컨텍스트를 flush할 필요는 없다.
때문에 이러한 보장이 확실하다면 아예 FlushModeType.COMMIT으로 설정해서
영속성 컨텍스트와 DB 사이의 동기화가 트랜잭션 당 1번만 일어나게 최적화를 이룰 수 있다.

em.setFlushMode(FlushModeType.COMMIT);

product.setPrice(2000);

em.flush(); // flush()를 적용해야지 JPQL을 에러없이 사용할 수 있다.

Product product2 = em.createQuery(
    "select ...",
    Prodcut.class
).getSingleResult(); // flush() 미적용.

Product product3 = em.createQuery(
    "select ...",
    Prodcut.class
).getSingleResult(); // flush() 미적용.

...

Product product100 = em.createQuery(
    "select ...",
    Prodcut.class
).getSingleResult(); // flush() 미적용.

em.commit(); // flush() 적용.

'JPA' 카테고리의 다른 글

13장 웹 애플리케이션과 영속성 관리  (0) 2023.09.07
12장 Spring Data JPA  (0) 2023.09.06
QueryDSL  (0) 2023.09.06
10장 객체지향 쿼리 언어  (0) 2023.09.04
9장 값 타입  (0) 2023.09.03