created at 2023-09-10
JPQL JOIN 들이 헷갈리는 부분이 있어서 정리해보았습니다.
JPQL 에는 총 4 가지 JOIN 방식이 존재합니다. 그리고 이 JOIN 방식에 따라 영속성 컨텍스트로의 로딩 전략이 달라집니다.
JPQL 에서 JOIN 을 사용하려면 연관관계를 엔티티에 설정해주어야만 합니다. 그렇지 않다면 Theta Join 을 사용해야합니다.
Theta Join 은 Cartesian Product 로 곱 조인을 수행하게 됩니다. LEFT 나 INNER 조인을 수행하지 못합니다.
먼저 아래의 예제와 여러 상황을 함께 볼까요?
SELECT o FROM Order o {JOIN 형태} o.customer c WHERE c.name = 'John'
- Order 가 Customer 을 LAZY 전략으로 fetch 하고, customer 가 null 이 아닐 때
- JOIN (INNER JOIN) : Order 만 영속성 컨텍스트에 로딩됩니다.
- JOIN FETCH (INNER JOIN FETCH) : Order 와 Customer 가 영속성 컨텍스트에 로딩됩니다.
- LEFT JOIN (LEFT OUTER JOIN) : Order 만 영속성 컨텍스트에 로딩됩니다.
- LEFT JOIN FETCH (LEFT OUTER JOIN FETCH) : Order 와 Customer 가 영속성 컨텍스트에 로딩됩니다.
- Order 가 Customer 을 LAZY 전략으로 fetch 하고, customer 가 null 일 때
- JOIN (INNER JOIN) : Order 만 영속성 컨텍스트에 로딩됩니다.
- JOIN FETCH (INNER JOIN FETCH) : 아무것도 로딩되지 않습니다.
- LEFT JOIN (LEFT OUTER JOIN) : Order 만 영속성 컨텍스트에 로딩됩니다.
- LEFT JOIN FETCH (LEFT OUTER JOIN FETCH) : Order 만 영속성 컨텍스트에 로딩됩니다.
- Order 가 Customer 을 EAGER 전략으로 fetch 하고, customer 가 null 이 아닐 때
- JOIN (INNER JOIN) : Order 와 Customer 가 영속성 컨텍스트에 로딩됩니다.
- JOIN FETCH (INNER JOIN FETCH) : Order 와 Customer 가 영속성 컨텍스트에 로딩됩니다.
- LEFT JOIN (LEFT OUTER JOIN) : Order 와 Customer 가 영속성 컨텍스트에 로딩됩니다.
- LEFT JOIN FETCH (LEFT OUTER JOIN FETCH) : Order 와 Customer 가 영속성 컨텍스트에 로딩됩니다.
- Order 가 Customer 을 EAGER 전략으로 fetch 하고, customer 가 null 일 때
- JOIN (INNER JOIN) : 아무것도 로딩되지 않습니다.
- JOIN FETCH (INNER JOIN FETCH) : 아무것도 로딩되지 않습니다.
- LEFT JOIN (LEFT OUTER JOIN) : Order 만 영속성 컨텍스트에 로딩됩니다.
- LEFT JOIN FETCH (LEFT OUTER JOIN FETCH) : Order 만 영속성 컨텍스트에 로딩됩니다.
예제를 보면서 아래의 각 JOIN 별 설명을 확인한다면 더욱 빠르게 이해될거에요!
- JOIN (INNER JOIN):
- 목적: 연관된 엔티티를 조인하기 위함입니다. 주로 쿼리의 WHERE 절이나 SELECT 절에서 추가 정보를 필요로 할 때 사용됩니다.
- 로딩 전략: 해당 엔티티의 로딩 전략 (Lazy 또는 Eager)에 따라 연관된 엔티티를 로드합니다.
- 결과: 조인 조건에 맞지 않는 기본 엔티티는 결과에서 제외됩니다.
- JOIN FETCH (INNER JOIN FETCH):
- 목적: 연관된 엔티티를 즉시 로딩하기 위한 목적입니다.
- 로딩 전략: 연관된 엔티티를 강제로 즉시 로드합니다.
- 결과: 조인 조건에 맞지 않는 기본 엔티티는 결과에서 제외됩니다.
- LEFT JOIN (LEFT OUTER JOIN):
- 목적: 기본 엔티티와 연관된 엔티티를 조인하기 위한 목적입니다. 연관된 엔티티가 없더라도 기본 엔티티는 결과에 포함됩니다.
- 로딩 전략: 해당 엔티티의 로딩 전략 (Lazy 또는 Eager)에 따라 연관된 엔티티를 로드합니다.
- 결과: 기본 엔티티는 항상 결과에 포함됩니다. 연관된 엔티티가 없으면 null로 처리됩니다.
- LEFT JOIN FETCH (LEFT OUTER JOIN FETCH):
- 목적: 기본 엔티티와 연관된 엔티티를 함께 즉시 로딩하는 것이 목적입니다.
- 로딩 전략: 연관된 엔티티를 강제로 즉시 로드합니다.
- 결과: 기본 엔티티는 항상 결과에 포함됩니다. 연관된 엔티티가 없으면 null로 처리됩니다.