728x90
@EntityGraph?
- 연관관계를 맺은 엔티티들을 SQL 한번에 조회
- fetch join과 매우 유사하다고 생각
연관된 엔티티를 한번에 조회하는 다양한 방법
가정
- Member와 Team은 N:1 양방향 연관관계를 가짐
- member1은 team1, member2는 team2, member3은 team3, member4는 team4
- member, team 지연로딩 설정
List<Member> members = memberRepository.findAll();
for (Member member : members) {
System.out.println("member.teamClass = " + member.getTeam().getClass());
System.out.println("member.team = " + member.getTeam().getName());
}
지연 로딩으로 인한 N+1 문제
- member.teamClass
- LAZY이기 때문에 실제 엔티티가 아닌 프록시 객체를 가지는 것을 알 수 있다
- Member를 조회하기 위해 1개의 쿼리를 날렸지만 각 Member의 Team 엔티티를 사용하기 위해서는 연관된 엔티티의 개수(N)만큼 쿼리를 날려야한다
- 현재 각 Member와 연관된 Team 객체는 총 4개가 있으므로 4개의 select 쿼리가 나가는 것을 알 수 있다
- 이러한 문제를 "지연로딩을 통한 N+1"이라고 한다
JPQL의 fetch join
@Query("select m from Member m join fetch m.team")
@Override
List<Member> findAll();
- Member를 조회할 때, 연관된 엔티티들을 조회하여 가져온다
- Team class를 보면 앞서 지연로딩과 다르게 proxy 객체가 아닌 실제 엔티티임을 알 수 있다
하지만 매번 fetch join을 할 때마다 JPQL을 작성해야한다
"간단한" fetch join을 편하게 사용하기 위해 spring data jpa가 "@EntityGraph"라는 것을 제공한다
@EntityGraph
@Override
@EntityGraph(attributePaths = {"team"})
List<Member> findAll();
- attributePaths를 이용하여 연관된 엔티티를 지정하여 페치 조인할 수 있다
- fetch join 사용했을 때의 쿼리가 같고, Team 클래스 또한 실제 엔티티라는 것을 알 수 있다
@EntityGraph을 다양한 방법으로 사용
앞서 배웠던 쿼리 메서드에 @EntityGraph를 사용할 수 있으며, "공통 메서드"를 오버라이딩하여 사용할 수 있다
공통 메서드를 오버라이딩하여 사용( CrudRepository 메서드)
@Override
@EntityGraph(attributePaths = {"team"})
List<Member> findAll();
JPQL + @EntityGraph
@EntityGraph(attributePaths = {"team"})
@Query("select m from Member m")
List<Member> findMemberEntityGraph();
메서드 이름으로 쿼리 생성하는 메서드에서 사용
@EntityGraph(attributePaths = {"team"})
List<Member> findByUsername(String username);
@NamedEntityGraph
@NamedEntityGraph(name = "Member.all", attributeNodes = @NamedAttributeNode("team"))
public class Member {
/// 코드
}
@EntityGraph("Member.all")
List<Member> findEntityGraphByUsername(@Param("username") String username);
- 멤버를 조회할 때마다 "자주" 팀을 같이 사용하기 때문에 사용하는 경우가 많다
@EntityGraph랑 fetch join이랑 다른 점이 있을까?
- join fetch을 명시하여 사용할 경우(별 다른 옵션 지정X) join 전략이 inner join
- @EntityGraph는 left outer join
앞서 "JPQL의 fetch join" 과 "@EntityGraph"의 쿼리를 참고해보면 알 수 있다
JPQL + @EntityGraph 쿼리도 left outer join을 사용할까에 대해 궁금할 수도 있어 올려보겠다
left outer join을 사용한다
REFERENCES
728x90
'Spring 강의 > Spring data JPA' 카테고리의 다른 글
벌크 연산 (0) | 2022.04.12 |
---|---|
페이징과 정렬 (0) | 2022.04.11 |
쿼리 메서드 (0) | 2022.04.08 |