-
JPA 1대다 fetch join 주의사항공부방 2024. 4. 2. 01:34더보기
김영한님의 JPA 강의를 보다가 1대다 fetch join 시 주의해야할 사항이 있고 어떤식으로 처리하는지 정리해두면 나중에 보기 좋을것 같아 정리
도메인
사용 쿼리
public List<Order> findAllWithItem() { return em.createQuery( "select distinct o from Order o" + " join fetch o.member m" + " join fetch o.delivery d" + " join fetch o.orderItems oi" + " join fetch oi.item i", Order.class) .getResultList(); }
문제 사항
기본적으로 쿼리에 distinct 가 들어간 이유는 Order 와 OrderItem 이 일대다 관계이기때문에 그냥 조회를 해버리면 중복된 자료가 뻥튀기되어 나오기 때문이다.
위의 리스트 조회 쿼리를 사용하면 페이징 처리가 안된다. Order 기준으로 페이징을 해야하는데 DB 입장에서는 일대다 관계로 늘어난 결과들을 어떻게 페이징 처리할지 모르기 때문이다. 여기서 만약 페이징 처리를 넣어버린다면 하이버네이트는 DB의 모든 데이터를 읽어오고, 메모리에서 페이징을 해버린다. 듣기만 해도 굉장히 위험해 보인다.
해결 방안
이 경우 페이징 처리를 하기 위해선 다음과 같은 방법이 있다.
우선 문제가 되는 1대다 관계를 제외하고 ToOne(OneToOne, ManyToOne) 관계만 fetch join 해서 가져온다. 이는 결과 row를 증가시키지 않기 때문에 페이징에 전혀 문제가 없다.
이렇게 결과를 가져온다음 문제가 발생했던 1대다 관계의 컬렉션은 지연 로딩으로 별도로 조회를 한다. 이 지연로딩 성능의 최적화를 위해 hibernate.default_batch_fetch_size 를 설정하여 글로벌로 처리하거나, @BatchSize 등을 이용해 개별로 최적화 할 수 있다. 이 옵션을 이용하면 조회 쿼리가 IN 쿼리로 나가기 때문에 한번에 조회가 된다.
출처
https://inf.run/CU9mR - 김영한
실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화 | 김영한 - 인프런
김영한 | 스프링 부트와 JPA를 활용해서 API를 개발합니다. 그리고 JPA 극한의 성능 최적화 방법을 학습할 수 있습니다., 스프링 부트, 실무에서 잘 쓰고 싶다면? 복잡한 문제까지 해결하는 힘을 길
www.inflearn.com
'공부방' 카테고리의 다른 글
RabbitMQ 와 Kafka (0) 2024.07.12 Proxy 와 Reverse Proxy (0) 2024.06.18 ElasticSearch 정리 (0) 2023.12.25 파이프라인 프로토콜 (1) 2023.11.22 HTTPS 통신 과정 (0) 2023.11.15