✅ 엔티티 페치 조인 ✅ 컬렉션 페치 조인 ✅ DISTINCT
연관된 엔티티나 컬렉션을 SQL 한 번에 함께 조회하는 기능
join fetch
예 : 회원을 조회하면서 연관된 팀도 함께 조회
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
Team teamA = new Team();
teamA.setName("팀A");
em.persist(teamA);
Team teamB = new Team();
teamB.setName("팀A");
em.persist(teamB);
Member member1 = new Member();
member1.setUsername("회원1");
member1.setTeam(teamA);
em.persist(member1);
Member member2 = new Member();
member2.setUsername("회원2");
member2.setTeam(teamA);
em.persist(member2);
Member member3 = new Member();
member3.setUsername("회원3");
member3.setTeam(teamB);
em.persist(member3);
em.flush();
em.clear();
String query = "select m From Member m";
List<Member> result = em.createQuery(query, Member.class)
.getResultList();
for (Member member : result){
System.out.println("member = " + member.getUsername() + ", " + member.getTeam().getName());
}
Member와 Team의 연관관계가 @ManyToOne(fetch = FetchType.LAZY)으로 지연로딩이기 때문에
회원1 : 팀A -> sql로 조회
회원2 : 팀A -> 1차캐시에서 조회
회원3 : 팀B -> sql로 조회
총 3번의 쿼리가 날라간다.
👉 최악의 경우 팀이 모두 다르다면 회원이 N명일 때 1 + N번의 쿼리가 필요하다.
👉 굉장히 비효율 적이므로 페치 조인을 통해 지연로딩 없이, 한방 쿼리로 조회한다.
String query = "select m From Member m join fetch m.team";
페치 조인 쿼리를 날릴 때 모든 것을 조인하여 영속성 컨텍스트에 올려놓으므로
반복문에서 새로운 쿼리를 날릴 필요가 없다고 보면 됨
👉 페치 조인으로 회원과 팀을 함께 조회해서 지연 로딩이 발생하지 않음
일대다 관계
JPQL
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'
// ... 위와 동일
String query = "select t From Team t join fetch t.members";
List<Team> result = em.createQuery(query, Team.class)
.getResultList();
for (Team team : result){
System.out.println("team = " + team.getName() + " | members = " + team.getMembers().size());
}
team = 팀A | members = 2
team = 팀A | members = 2
team = 팀A | members = 1
👉 db상 일대다 조인해서 가져오는 것이기 때문에 같은 정보가 또 조회되는 문제가 있음
- SQL에 DISTINCT를 추가
- 애플리케이션에서 엔티티 중복 제거
select distinct t
from Team t join fetch t.members
where t.name = ‘팀A’
- 모든 것을 페치 조인으로 해결할 수 없으므로 객체 그래프를 유지할 때 사용하면 효과적이다.
- 여러 테이블을 조인해서 엔티티가 가진 모양이 아닌 전혀 다른 결과를 내야 하면,
페치 조인 보다는 일반 조인을 사용하고 필요한 데이터들만 조회해서 DTO로 반환하는 것이 효과적