[실전! 스프링 데이터 JPA] @EntityGraph - 연관된 엔티티들을 SQL 한번에 조회

강신현·2022년 8월 9일
0

✅ @EntityGraph ✅ @NamedEntityGraph


필요성

지연로딩에서의 N+1 문제

member team은 지연로딩 관계이다.
member를 find하면 team은 가짜, 프록시로 가져와 진다.
따라서 team의 실제 데이터가 필요할 때는 조회할 때 마다(team.getName) 쿼리가 실행된다.
즉, team의 실제 데이터가 필요할 때마다 네트워크로 쿼리를 날리기 때문에 비효율적이다.
이것을 N+1 문제라고 하고

쿼리 하나로 member와 관련된 team에 대한 정보도 프록시가 아닌 실제 객체로 모두 가져오는 방법으로 N+1 문제를 해결할 수 있다.

아래처럼 JPQL로 패치 조인을 만들어 문제를 해결할 수는 있지만, 경우마다 쿼리문을 작성해야 하는 번거로움이 있다.

 @Query("select m from Member m left join fetch m.team")
 List<Member> findMemberFetchJoin();

JPQL vs @EntityGraph

  • 간단한 경우 : @EntityGraph로 간단하게 패치조인을 구현
  • 복잡한 경우 : JPQL로 직접 패치조인을 구현

@EntityGraph

연관된 엔티티들을 SQL 한번에 조회

public interface MemberRepository extends JpaRepository<Member, Long> {
	// @EntityGraph
    
    // 1. 공통 메서드 오버라이드
    @Override
    @EntityGraph(attributePaths = {"team"})
    List<Member> findAll();
    
    // 2. JPQL + 엔티티 그래프
    @EntityGraph(attributePaths = {"team"})
    @Query("select m from Member m")
    List<Member> findMemberEntityGraph();
    
    // 3. 메서드 이름으로 쿼리에서 특히 편리하다.
    @EntityGraph(attributePaths = {"team"})
    List<Member> findEntityGraphByUsername(String username);
}

@NamedEntityGraph

@NamedQuery처럼 엔티티에 선언하여 사용하는 방법

(강사님은 잘 사용하지 않는다고 함, 아마 엔티티가 더러워져서 인듯)

  • Member
@NamedEntityGraph(name = "Member.all", attributeNodes =
@NamedAttributeNode("team"))
@Entity
public class Member {
	...
}
  • MemberRepository
public interface MemberRepository extends JpaRepository<Member, Long> {
    @EntityGraph("Member.all")
    @Query("select m from Member m")
    List<Member> findMemberEntityGraph();
}

강의 출처

[인프런 - 김영한] 실전! 스프링 데이터 JPA

profile
땅콩의 모험 (server)

0개의 댓글