본문 바로가기

CS 잡지식

@EntityGraph(feat. Spring Data JPA가 제공하는 Fetch Join)

    public interface MemberReposiotry extends JpaRepository<Member,Long> {
    
    //Spring Data JPA로 Fetch Join 구현 1
     @Query("select m from Member m left join fetch m.team")
     List<Member> findMemberFetchJoin();
     //이 방법만으로도 충분히 fetch join을 간편하게 구현이 가능하나,
     //Spring Data JPA는 [@EntityGraph]를 이용하여, 기존과 같이 쿼리 메서드 명으로 fetch join을 구현하는 기능을 지원한다.

     //Spring Data JPA로 Fetch Join 구현 2
     @EntityGraph(attributePaths = {"team"} ) // Member -> Team ( 다 : 1 && 단방향 ) 관계이며, Member가 연관 관계의 주인이다.
     @Override // JpaRepository 공통 인터페이스에는 이미 findAll()이 있으므로, 쿼리 메서드 기능을 이용하기 위해서는 오버라이딩을 해야 한다.
     List<Member> findAll(); // Member를 조회할 때, (N+1) 문제를  @EntityGraph(attributePaths = {"team"} )이 해결!!!
     //attributePaths = {"team"}는 Member를 조회할 때, Member와 연관 관계에 있는 엔티티 중 어떤 엔티티를 함께 fetch join 해올것인지를 지정


      //Spring Data JPA로 Fetch Join 구현 3
      @EntityGraph("Member.all")
      @Query("select m from Member m")
      List<Member> findMemberEntityGraph(); // 참고로, 이 메서드 명은 Spring Data JPA의 쿼리 메서드의 형식을 지키고 있지 않기에 쿼리 메서드 기능은 사용 X

      //Spring Data JPA로 Fetch Join 구현 4
      @EntityGraph(attributePaths = {"team"})
      List<Member> findEntityGraphByUsername(@Param("username") String username); //이건 쿼리 메서드 기능을 사용하고 있다.
@Test@Transactional
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);

    repository.save(new Member("member1", 10, teamA));
    repository.save(new Member("member2", 20, teamB));

    entityManager.flush();
    entityManager.clear();


    //when
    List<Member> members = repository.findAll(); // @EntityGraph(attributespath = {"team}으로 (n+1) 문제 해결!

    //then
    for (Member member : members) {
        member.getTeam().getName();
    }

 

실무 팁

-> 간단 간단한 fetch join JPQL문 같은 경우에는 @EntityGraphy을 사용하면 되고

복잡한 fetch join JPQL의 경우는, 순수 JPQL로 직접 Fech join JPQL문을 짜면 된다.