JPA 톺아보기 - JPQL JOIN

Janek·2023년 2월 25일
0

JPA 톺아보기

목록 보기
10/10
post-thumbnail

해당 포스팅은 인프런에서 제공하는 김영한 님의 '자바 ORM 표준 JPA 프로그래밍 - 기본편'을 수강한 후 정리한 글입니다. 유료 강의를 정리한 내용이기에 제공되는 예제나 몇몇 내용들은 제외하였고, 정리한 내용을 바탕으로 글 작성자인 저의 언어로 다시 작성한 글이기에 서술이 부족하거나 잘못된 내용이 있을 수 있습니다. 그렇기에 해당 글은 개념에 대한 참고 정도만 해주시고, 강의를 통해 학습하시기를 추천합니다.

JPQL 조인

내부 조인과 외부 조인

JPQL의 조인은 SQL과 기능이 같지만, 문법에 약간의 차이가 있다. JPQL 조인의 가장 큰 특징은 다른 엔티티와 연관관계를 가지기 위해 사용하는 필드인 연관 필드를 사용해 조인한다는 것이다.

SELECT ... FROM Member m JOIN m.team t

외부 조인 또한 기능상 SQL의 외부 조인과 같다.

SELECT m FROM Member m LEFT JOIN m.team t

컬렉션 조인

일대다 관계나 다대다 관계처럼 컬렉션을 사용하는 곳에 조인하는 것을 컬렉션 조인이라 한다.

  • 회원 -> 팀 : 다대일 조인, 단일 값 연관 필드(m.team) 사용
  • 팀 -> 회원 : 일대다 조인, 컬렉션 값 연관 필드(m.members) 사용

세타 조인

전혀 관련 없는 엔티티도 세타 조인을 통해 조인할 수 있다. 세타 조인은 내부 조인만을 지원한다.

SELECT COUNT(m) FROM Member m, Team t WHERE m.username = t.name

ON

ON 절을 사용하면 조인 대상을 필터링하고 조인할 수 있다. 내부 조인의 ON절은 WHERE 절과 같은 결과를 반환하므로 보통 외부 조인에서만 사용한다.

SELECT m, t FROM Memeber m LEFT JOIN m.team t ON t.name = "A"

페치 조인

페치 조인은 JPQL에서 성능 최적화를 위해 제공하는 기능으로 연관된 엔티티나 컬렉션을 한 번에 같이 조회하는 기능이다. 페치 조인의 문법은 다음과 같다.

[ LEFT [OUTER] | INNER ] JOIN FETCH 조인 경로

엔티티 페치 조인

SELECT m FROM Member m JOIN FETCH m.team

위와 같은 JPQL 쿼리를 사용할 경우 연관된 엔티티나 컬렉션을 함께 조회할 수 있다. 일반적인 JPQL 조인과는 다르게 m.team 다음에 별칭이 존재하지 않으며, 페치 조인은 별칭을 사용할 수 없다.(하이버네이트는 허용)

페치 조인을 사용하면 지연 로딩으로 설정된 엔티티 객체를 조회할 때도 프록시가 아닌 실제 엔티티 객체를 조회할 수 있다. 그렇기에 준영속 상태가 되더라도 조회 된 범위 내에서 객체 그래프 탐색이 가능하다.

컬렉션 페치 조인

SELECT t FROM Team t JOIN FETCH t.members WHERE t.name = 'TeamA'

위의 쿼리문 실행 시 팀을 조회하며 연관된 회원 컬렉션도 함께 조회한다. 조회된 회원 컬렉션의 각 객체들은 같은 팀 객체를 참조하게된다.

페치 조인과 DISTINCT

JPQL의 DISTINCT는 SQL에 DISTINCT를 추가함과 동시에 어플리케이션에서 한 번 더 중복을 제거한다.

페치 조인과 일반 조인

JPQL은 결과를 반환할 때 SELECT절에 지정한 엔티티만을 조회할 뿐 연관관계까지 고려하지 않는다. 그렇기 때문에 연관관계 설정시 지연 로딩으로 설정하면 프록시나 아직 초기화되지 않은 컬렉션 래퍼를 반환한다. 반면 즉시 로딩으로 설정할 경우 해당 컬렉션을 즉시 로딩하기 위해 쿼리를 한 번 더 실행하게 된다. 하지만 페치 조인을 사용하면 연관된 엔티티를 함께 조회한다.

페치 조인의 특징과 한계

페치 조인 사용시 SQL을 최적화하여 호출 횟수를 줄일 수 있다. 페치 조인은 글로벌 로딩 전략보다 우선시 되기에 기본적으로 글로벌 로딩 전략을 지연 로딩으로 설정하고, 최적화가 필요한 조회시 페치 조인을 적용하는 것이 좋다.

그러나 페치 조인은 조인 대상에 별칭을 줄 수 없어 SELECT, WHERE, 서브 쿼리에서 페치 조인 대상을 사용할 수 없다. 또한 둘 이상의 컬렉션을 페치할 수 없다는 점과 페이징 API를 사용할 수 없다는 단점이 존재한다.

profile
만들고 나누며, 세상을 이롭게 하고 싶습니다.

0개의 댓글