-
1. 페치 조인의 대상에는 별칭을 줄 수가 없다.
"select t from Team t join fetch t.members as m"
뒤에 'as m'처럼 별칭을 붙일 수가 없다. 페치 조인은 연관된 데이터들을 모두 가져오는 것이기 때문에 그 중에 몇 개의 데이터만 가져온다던지 하는 쿼리는 하지 않는다. 하이버네이트에서 지원하기는 하지만 가급적 사용하지 않도록 하자.
페치 조인은 연간된 데이터를 모두 가져오는 것인데, 10개중에 5개만 가져오게 된다면 잘못하면 데이터가 지워질 수도 있거나 나중에 영속성 컨텍스트에서 문제가 될 수도 있다.
꼭 필요한 경우에는 어쩌다 한 번 쓸 수는 있지만 되도록 사용하면 안된다.
2. 둘 이상의 컬렉션은 페치 조인을 할 수가 없다.
일대 다와 일대 다의 매칭이므로 일대 다대 다이기 때문에 데이터가 폭발적으로 증가할 수 있다.
그렇기 때문에 컬렉션은 무조건 하나만 지정해야한다.
3. 컬렉션을 페치 조인하면 페이징 API를 사용할 수 없다. (setFirstResult, setMaxResults)
페이징은 DB 중심이기 때문에 페이징으로 row를 제한해버리면 데이터가 잘려서 나오게 된다. JPA는 db에서 내려준 결과만 알기 때문에 페이징을 못한다.
일대일, 다대일 같은 단일 값 연관 필드들은 페치 조인해도 페이징이 가능하다.
하이버네이트는 경고 로그를 남기고 메모리에서 페이징을 하는데 매우 위험하다.
페이징을 해결하기 위해서는 select 방향을 뒤집는 방법이 있다.
String query = "select t from Team t join fetch t.members" String query = "select m from Member m join fetch m.team" List<Team> result = em.createQuery(query, Team.class) .setMaxResults(3) .getResultList();
일대일을 다대일로 바꿔서 페이징을 사용할 수 있도록 한다.
실무에서 글로벌 로딩 전략은 모두 지연 로딩이다.
최적화가 필요한 곳은 페치 조인을 적용하고, JPA의 경우에는 대부분의 성능 문제를 페치 조인으로 잡을 수 있다.
페치 조인 정리
- 모든 것을 페치 조인으로 해결할 수는 없다.
- 페치 조인은 객체 그래프를 유지할 때 사용하면 효과적이다.
- 여러 테이블을 조인해서 엔티티가 가진 모양이 아닌 전혀 다른 결과를 내야하면, 페치 조인 보다는 일반 조인을 사용하고 필요한 데이터들만 조회해서 DTO로 반환하는 것이 효과적이다.
'JPA > JPQL' 카테고리의 다른 글
Named 쿼리 (0) 2023.08.09 엔티티를 직접 사용하기 (0) 2023.08.09 페치 조인(fetch join) (0) 2023.08.09 경로 표현식 (0) 2023.08.09 조건식 (CASE) (0) 2023.07.14