[JPA] @EntityGraph

EB·2024년 1월 19일
post-thumbnail

@EntityGraph

엔티티 조회시점에 연관된 엔티티들을 함께 조회하는 기능.

현재 Member와 Team은 일대다/다대일 관계이고,LAZY(지연로딩)이 설정되어있는 상태이다.
Member -> OneToMany
Team -> ManyToOne

member를 모두 조회하고 for문을 통해 member에 대한 정보를 조회해보자.

 System.out.println("members = " + member.getUsername());
 System.out.println("member.teamClass = " + member.getTeam().getClass());
       
  • member1의 이름이 조회되고, member1의 team은 지연로딩으로 설정 되어있기때문에 team의 객체의 값을 실제로 조회하기 전까지는 team은 프록시(Team$HibernateProxy)로 존재하는 것을 확인할 수 있다.
    System.out.println("member.team = " + member.getTeam().getName());
  • member.getTeam().getName()을 통해 team의 실제로 조회를 해야하기 때문에 team의 id를 가지고 조회하는 쿼리로 DB에서 데이터를 조회한다.
    이렇게 쿼리가 2개가 나오게 되었다.

N+1문제

fetch join을 사용해서 member를 조회할 때 연관된 팀을 한방쿼리로 조회해와야한다.

JPQL

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

fetch join
연관 관계가 있는 것을 DB의 조인을 통해 한번에 조회해오는 것을 말한다.
조인했을 때 team 데이터까지 모두 조인해 데이터를 넣어준다.

이제 위에 작성한 테스트코드에서 findMemberFetchJoin()을 호출하면 아래와 같이 한번에 모두 조인된 상태로 조회하게 된다. team 가짜 프록시 객체가 아닌 진짜 엔티티가 조회된다.

JPQL 사용대신 @EntityGraph으로 간단하게 사용할 수 있다.
그리고 JPQL에 @EntityGraph를 사용해도 된다!

@Override
@EntityGraph(attributePaths = {"team"})
List<Member> findAll();

@EntityGraph(attributePaths = {"team"})
@Query("select m from Member m")
List<Member> findMemberEntityGraph();

@EntityGraph(attributePaths = {"team"})
List<Member> findEntityGraphByUsername(@Param("username") String username);
profile
👩‍💻✨junior developer

0개의 댓글