연관된 엔티티들을 SQL 한번으로 조회하는 방법이다.
fetch join도 있지만 조금 더 간단한 방법이다.
member -> team이 지연로딩 관계로 엮여있다면, 아래 코드에서는 team 데이터를 조회 할 때 마다 쿼리가 실행된다.
(N+1 문제 발생...)
그렇다면 N+1문제를 해결하는 방법은 무엇이 있을까.
@Test
public void findMemberLazy() throws Exception {
//given
//member1 -> teamA
//member2 -> teamB
Team teamA = new Team("teamA");
Team teamB = new Team("teamB");
teamRepository.save(teamA);
teamRepository.save(teamB);
memberRepository.save(new Member("member1", 10, teamA));
memberRepository.save(new Member("member2", 20, teamB));
em.flush();
em.clear();
//when
List<Member> members = memberRepository.findAll();
//then
for (Member member : members) {
member.getTeam().getName();
}
}
N+1을 해결하기 위한 가장 흔한 방법으로 fetch Join이 있다.
@Query("select m from Member m left join fetch m.team")
List<Member> findMemberFetchJoin();
Spring Data JPA는 EntityGraph 기능을 이용해 편리하게 N+1 문제를 해결 할 수 있다.
//공통 메서드 오버라이드
@Override
@EntityGraph(attributePaths = {"team"})
List<Member> findAll();
//JPQL + 엔티티 그래프
@EntityGraph(attributePaths = {"team"})
@Query("select m from Member m")
List<Member> findMemberEntityGraph();
//메서드 이름으로 쿼리에서 특히 편리하다.
@EntityGraph(attributePaths = {"team"})
List<Member> findByUsername(String username)
정리해 보자면 EntityGraph기능은 fetch join의 간편 버전이다.
내부적으로는 Left Outer Join을 사용한다.