.
을 찍어서 객체 그래프를 탐색하는 것
select m.username -> 상태 필드
from Member m
join m.team t -> 단일 값 연관 필드
join m.orders o -> 컬렉션 값 연관 필드
where t.name = '팀A'
state field
): 단순히 값을 저장하기 위한 필드association field
): 연관관계를 위한 필드@ManyToOne
, @OneToOne
, 대상이 엔티티 (Ex. m.team
) @OneToMany
, @ManyToMany
, 대상이 컬렉션 (Ex. m.orders
)inner join
) 발생, 탐색 ⭕ FROM
절에서 명시적 조인을 통해 별칭을 얻으면 별칭을 통해 탐색이 가능하다.명시적 조인: join
키워드 직접 사용
select m from Member m join m.team t
묵시적 조인: 경로 표현식에 의해 묵시적으로 SQL 조인 발생 (내부 조인만 가능)
select m.team from Member m
⭐ 가급적 묵시적 조인 대신 명시적 조인을 사용하자 ❗
- 조인은 SQL 튜닝에서 중요 포인트!
- 묵시적 조인은 조인이 일어나는 상황을 한눈에 파악하기 어렵다. → 그냥 쓰지 말자😣
⭐ 실무에서 정말정말 중요하다!
join fetch
명령어를 사용한다.[ LEFT [OUTER] | INNER ] JOIN FETCH 조인 경로
T.*
)도 함께 SELECT한다.select m from Member m join fetch m.team
SELECT M.*, T.* FROM MEMBER M
INNER JOIN TEAM T ON M.TEAM_ID=T.ID
fetch join
을 사용하면 내부적으로 inner join
을 사용한다.inner join
이기 때문에 (팀이 없는 회원인) 회원4
는 빠진다.select t
from Team t join fetch t.members
where t.name = '팀A'
SELECT T.*, M.*
FROM TEAM T
INNER JOIN MEMBER M ON T.ID=M.TEAM_ID
WHERE T.NAME = '팀A'
Team
은 하나지만 Member
는 1개 이상일 수 있다.팀A
에 해당하는 멤버가 회원1
, 회원2
로 두 개이기 때문에 조회 결과가 두 줄로 나온다.페치 조인으로 데이터가 중복된 것을 처리하기 위해
DISTINCT
키워드를 사용한다.
DISTINCT
는 중복된 결과를 제거하는 명령이다.DISTINCT
는 2가지 기능을 제공한다.DISTINCT
추가select distinct t
from Team t join fetch t.members
where t.name = '팀A'
DISTINCT
를 추가하지만 데이터가 다르므로 SQL 결과에서 중복 제거 실패!ID(PK)
와 NAME
이 다르다.)DISTINCT
가 추가로 어플리케이션에서 중복 제거를 시도한다.Team
엔티티 제거일반 조인 실행 시 연관된 엔티티를 함께 조회하지 않는다.
select t
from Team t join t.members m
where t.name = '팀A'
SELECT T.*
FROM TEAM T
INNER JOIN MEMBER M ON T.ID=M.TEAM_ID
WHERE T.NAME = '팀A'
페치 조인은 연관된 엔티티를 함께 조회한다.
select t
from Team t join fetch t.members
where t.name = '팀A'
SELECT T.*, M.*
FROM TEAM T
INNER JOIN MEMBER M ON T.ID=M.TEAM_ID
WHERE T.NAME = '팀A'
setFirstResult
,setMaxResults
)를 사용할 수 없다. @OneToMany(fetch = FetchType.LAZY) //글로벌 로딩 전략
📌 정리: 모든 것을 페치 조인으로 해결할 수는 없다 ❗
- 페치 조인은 객체 그래프를 유지할 때 사용하면 효과적이다.
- 여러 테이블을 조인해서 엔티티가 가진 모양이 아닌 전혀 다른 결과를 내야 하면,
일반 조인을 사용 & 필요한 데이터들만 조회해서 DTO로 반환하는 것이 효과적이다.