DEV ℧ Developer Diary

[JPA] JPQL - 페치 조인2 - 한계

해당 포스트는 인프런 김영한님의 자바 ORM 표준 JPA 프로그래밍 - 기본편 을 듣고 정리한 글입니다.

페치 조인2 - 한계

페치 조인의 특징과 한계

  • 페치 조인 대상에는 별칭을 줄 수 없다.
    • 하이버네이트는 가능, 가급적 사용하는것이 안좋음. (fetch는 연관된 정보를 모두 가져오는 것이기 때문에, 의도된 동작이 안될 수 있다.)
  • 둘 이상의 컬렉션은 페치 조인 할 수 없다.
  • 컬렉션을 페치 조인하면 페이징 API(setFirstResult, setMaxResult)를 사용할 수 없다.
    • 일대일, 다대일 같은 단일 값 연관 필드들은 페치 조인해도 페이징 가능
    • 하이버네이트는 경고 로그를 남기고 메모리에서 페이징(매우 위험)
  • 경고 로그
23:34:03.314 [main] WARN org.hibernate.hql.internal.ast.QueryTranslatorImpl - HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!
23:34:03.316 [main] DEBUG org.hibernate.SQL -
    /* SELECT
        t
    FROM
        Team t
    join
        fetch t.members m */ select
            team0_.id as id1_3_0_,
            members1_.id as id1_0_1_,
            team0_.age as age2_3_0_,
            team0_.name as name3_3_0_,
            members1_.age as age2_0_1_,
            members1_.TEAM_ID as team_id5_0_1_,
            members1_.type as type3_0_1_,
            members1_.username as username4_0_1_,
            members1_.TEAM_ID as team_id5_0_0__,
            members1_.id as id1_0_0__
        from
            Team team0_
        inner join
            Member members1_
                on team0_.id=members1_.TEAM_ID

컬렉션에서 fetch join을 사용할 수 없으니, @BatchSize 어노테이션을 연관관계 필드에 정의해서 사용 할 수 있다.

  • 연관된 엔티티들을 SQL 한 번으로 조회 - 성능 최적화
  • 엔티티에 직접 적용하는 글로벌 로딩 전략보다 우선함
    • @OneToMany(fetch = FetchType.LAZY) //글로벌 로딩 전략
  • 실무에서 글로벌 로딩 전략은 모두 지연 로딩
  • 최적화가 필요한 곳은 페치 조인 적용 (N+1 문제가 발생하는 곳에서만 사용해도 99%는 잡힘)

정리

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