페치 조인이란?
- SQL 조인 종류가 아니다
- JPQL에서 성능 최적화를 위해 제공하는 기능이다
- 연관된 엔티티나 컬렉션을 SQL 한 번에 함께 조회하는 기능이다
- join fetch 명령어 사용한다
엔티티 페치 조인
회원을 조회하면서 연관된 팀도 함께 조회한다. 쿼리는 다음과 같다.
select m from Member m join fetch m.team (SQL 1번)
SQL을 보면 회원 뿐만 아니라 팀도 함께 조회된다. 회원 조회 → 팀 조회로 SQL 2번 나가는 것을 페치 조인을 사용하면 쿼리가 나가는 횟수를 줄일 수 있다.
Member의 team에 Lazy 로딩이 설정되어 있어도 페치 조인이 우선시된다.
String jpql = "select m from Member m join fetch m.team";
List<Member> members = em.createQuery(jpql, Member.class).getResultList();
for (Member member : members) {
//페치 조인으로 회원과 팀을 함께 조회해서 지연 로딩X
System.out.println("username = " + member.getUsername() + ", " + "teamName = " + member.getTeam().name());
}
컬렉션 페치 조인
일대다 관계에서 사용하는 페치 조인을 컬렉션 페치 조인이라고 한다. 쿼리는 다음과 같다.
select t from Team t join fetch t.members where t.name = ‘팀A'
String jpql = "select t from Team t join fetch t.members where t.name = '팀A'"
List<Team> teams = em.createQuery(jpql, Team.class).getResultList();
for(Team team : teams) {
System.out.println("teamname = " + team.getName() + ", team = " + team);
for (Member member : team.getMembers()) {
//페치 조인으로 팀과 회원을 함께 조회해서 지연 로딩 발생 안함
System.out.println(“-> username = " + member.getUsername()+ ", member = " + member);
}
}
근데 컬렉션을 페치 조인을 하면 일대다 관계이기 때문에 데이터가 뻥튀기 된다. 즉, 중복 데이터가 조회된다.
SQL의 DISTINCT는 중복된 결과를 제거하는 명령이다.
[JPQL의 DISTINCT 2가지 기능 제공]
1. SQL에 DISTINCT를 추가
2. 애플리케이션에서 엔티티 중복 제거
DISTINCT를 사용한 쿼리는 다음과 같다. select distinct t from Team t join fetch t.members where t.name = ‘팀A’
SQL에 DISTINCT를 추가하지만 데이터가 다르므로 SQL 결과에서 중복 제거에 실패한다.
페치 조인의 특징과 한계
- 페치 조인 대상에는 별칭을 줄 수 없다 (하이버네이트는 가능, 가급적 사용X)
- 둘 이상의 컬렉션은 페치 조인 할 수 없다
- 컬렉션을 페치 조인하면 페이징 API(setFirstResult, setMaxResults)를 사용할 수 없다 (일대일, 다대일 같은 단일 값 연관 필드들은 페치 조인해도 페이징 가능)
- 연관된 엔티티들을 SQL 한 번으로 조회할 수 있다 → 성능 최적화
- 엔티티에 직접 적용하는 글로벌 로딩 전략보다 우선한다 @OneToMany(fetch = FetchType.LAZY) // 글로벌 로딩 전략
- 실무에서 글로벌 로딩 전략은 모두 지연 로딩으로 설정해야 한다
- 최적화가 필요한 곳은 페치 조인 적용하는 것이 좋다
'Back-end > Spring' 카테고리의 다른 글
[SpringBoot] 지연 로딩과 즉시 로딩 (0) | 2022.03.31 |
---|---|
[SpringBoot] 엔티티 매핑, 연관관계 매핑 (0) | 2022.02.06 |
[Spring] 영속성 컨텍스트 (0) | 2022.01.26 |
[SpringBoot] 컴포넌트 스캔과 의존관계 자동 주입 (@Component, @Autowired, @RequiredArgsConstructor) (0) | 2022.01.16 |
SOLID 적용하여 리팩토링하기 (0) | 2022.01.10 |