[JPA] fetch join

hi·2022년 10월 16일

fetch join

  • SQL 조인 종류가 아닌, JPQL에서 성능 최적화를 위해 제공
  • 연관된 엔티티나 컬렉션을 SQL 한 번에 함께 조회

[ left [outer] | inner ] join fetch 조인경로


엔티티 페치 조인

ex. 회원을 조회하면서 연관된 팀도 함께 조회 (SQL 한 번에)

[JPQL]
select m from Member m join fetch m.team

👇 m만 조회했으나 t까지 함께 조회 실행

[SQL]
select m.~ , t.~ from Member m inner join Team t on m.team_id = t.id

  • @ManyToOne 지연로딩 설정해도 fetch join 우선시

컬렉션 페치 조인

일대다 관계

[JPQL]
select t from Team t join fetch t.members where t.name = ‘팀A'

👇

[SQL]
SELECT T.~ , M.~ FROM TEAM T INNER JOIN MEMBER M ON T.ID=M.TEAM_ID WHERE T.NAME = '팀A'

결과가 중복


중복 제거 DISTINCT

SQL의 DISTINCT

  1. 중복된 결과를 제거

JPQL의 DISTINCT

  1. SQL에 DISTINCT 추가
    (but, 데이터가 달라 중복 제거 실패)

  2. 애플리케이션에서 엔티티 중복 제거
    같은 식별자를 가진 엔티티 제거


일반 조인과의 차이점

  • 일반 조인 실행시 연관된 엔티티를 함께 조회하지 않음
  • 페치 조인을 사용할 때만 연관된 엔티티도 함께 조회(즉시 로딩)
  • 페치 조인은 객체 그래프를 SQL 한번에 조회하는 개념

[JPQL]
select t from Team t join t.members m where t.name = ‘팀A'

👇

[SQL]
SELECT T.~
FROM TEAM T
INNER JOIN MEMBER M ON T.ID=M.TEAM_ID
WHERE T.NAME = '팀A'


특징과 한계

  • 페치 조인 대상에 별칭 불가
    ( 하이버네이트는 가능하나 가급적 사용 x )
  • 둘 이상의 컬렉션 페치 조인 불가
  • 컬렉션 페치 조인시 페이징 API(setFirstResult , setMaxResults) 사용 불가
    • 일대일, 다대일 같은 단일 값 연관 필드들은 페치 조인해도 페이징 가능
    • 하이버네이트는 경고 로그를 남기고 메모리에서 페이징 (매우 위험)
  • 연관된 엔티티들을 SQL 한 번으로 조회 - 성능 최적화
  • 엔티티에 직접 적용하는 글로벌 로딩 전략보다 우선함
    @OneToMany(fetch = FetchType.LAZY) //글로벌 로딩 전략
  • 실무에서 글로벌 로딩 전략은 모두 지연 로딩
  • 최적화가 필요한 곳은 페치 조인 적용

정리

  • 모든 것을 페치 조인으로 해결 불가
  • 페치 조인은 객체 그래피를 유지할 때 사용하면 효과적
  • 여러 테이블을 조인해 엔티티가 가진 모양이 아닌 전혀 다른 결과를 내야 하면,
    일반 조인을 사용 👉 필요한 데이터들만 조회해서 DTO로 반환하는 것이 효과적

0개의 댓글