오봉이와 함께하는 개발 블로그
스프링 데이터 JPA - @EntityGraph 본문
@EntityGraph
연관된 엔티티들을 SQL 한번에 조회하는 방법이다.@EntityGraph
에 대하여 정확하게 이해하기 위해서는 패치조인에 대하여 알고 있어야한다.
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id")
// '일대다'관계에서 '다'가 연관관계 주인이 되어 FK를 가진다.
private Team team;
@Test
public void findMemberLazy() throws Exception {
// given
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", 10, teamB));
em.flush();
em.clear();
// when
List<Member> members = memberRepository.findAll();
// then
for (Member member : members) {
System.out.println("member.getUsername() = " + member.getUsername());
System.out.println("member.getTeam().getClass() = " + member.getTeam().getClass());
System.out.println("member.getTeam().getName() = " + member.getTeam().getName());
}
}
@ManyToOne(fetch = FetchType.LAZY)
을 통해 LAZY
로 적용했기 때문에 member.getUsername()
을 했을 때는 Member
만 조회하는 쿼리가 나가고, Team
을 조회하는 쿼리는 나가지 않고, 프록시 객체가 나가게 된다.
(member.getTeam().getClass()
를 통해 조회하면 XXX.Team$HibernateProxy$XXXXX
가 출력된다.)
하지만, member.getTeam().getName();
을 통해서 Team
의 데이터를 조회하게 되면 Team
을 조회하는 쿼리도 나가게 된다.
member
-> team
은 지연로딩 관계이다.
따라서 다음과 같이 team
의 데이터를 조회할 때 마다 쿼리가 실행된다. (N+1 문제 발생)
N+1 문제를 해결하기 위해서는 연관된 엔티티를 한번에 조회하는 페치 조인이 필요하다.
JPQL 페치 조인
@Query("select m from Member m left join fetch m.team")
List<Member> findMemberFetchJoin();
위 코드를 실행해서 조회하면 조회 한 번에 Team에 대한 정보도 모두 조회하기 때문에 N+1 문제를 해결할 수 있다.
EntityGraph
스프링 데이터 JPA는 JPA가 제공하는 엔티티 그래프 기능을 편리하게 사용하게 도와준다.
이 기능을 사용하면 JPQL 없이 페치 조인을 사용할 수 있다. (JPQL + 엔티티 그래프도 가능)
//공통 메서드 오버라이드
@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> findEntityGraphByUsername(String username);
사실상 페치 조인(FETCH JOIN)의 간편 버전으로 LEFT OUTER JOIN을 사용한다.
NamedEntityGraph 사용 방법
NamedQuery
를 사용하듯 EntityGraph
를 NamedEntityGraph
로 사용할 수 있다.
@NamedEntityGraph(name = "Member.all", attributeNodes = @NamedAttributeNode("team"))
@Entity
public class Member {}
@EntityGraph("Member.all")
@Query("select m from Member m")
List<Member> findMemberEntityGraph();
인프런 김영한 지식공유자님 강의 : 실전! 스프링 데이터 JPA
'BE > JPA' 카테고리의 다른 글
스프링 데이터 JPA - 사용자 정의 리포지토리 구현 (0) | 2022.09.14 |
---|---|
스프링 데이터 JPA - JPA Hint & Lock (0) | 2022.09.14 |
스프링 데이터 JPA - 벌크성 수정 쿼리 (0) | 2022.09.13 |
스프링 데이터 JPA - 스프링 데이터 JPA 페이징과 정렬 (0) | 2022.09.13 |
스프링 데이터 JPA - 순수 JPA 페이징과 정렬 (0) | 2022.09.13 |