Programming/Spring

Spring Data JPA - @EntityGraph

잇(IT) 2023. 7. 26. 11:46

- ManyToOne의 관계에서 One의 관계에 있는 엔티티가 LAZY일 경우  One의 데이터를 조회할 때마다 쿼리가 실행된다.

 

@Test
    public void findMemberLazy() {
        //given
        //member1 -> teamA
        //member2 -> teamB

        Team teamA = new Team("teamA");
        Team teamB = new Team("teamB");
        teamRepository.save(teamA);
        teamRepository.save(teamB);

        Member member1 = new Member("member1", 10, teamA);
        Member member2 = new Member("member2", 10, teamA);

        memberRepository.save(member1);
        memberRepository.save(member2);

        em.flush();
        em.clear();

        //when
        List<Member> members = memberRepository.finAll("member1");

        for (Member member : members) {
            System.out.println("member = " + member.getUsername());
            System.out.println("member.getTeam().getClass() = " + member.getTeam().getClass());
            System.out.println("member.getTeam().getName() = " + member.getTeam().getName());
        }
    }

- 위와 같이 LAZY이기 때문에 프록시 객체를 사용하여 해당 엔티티 조회가 필요할 때 쿼리를 날려 데이터를 조회한다.


- fetch join으로 변경

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

- fetch join을 사용하게 되면 LAZY(지연로딩) 이전에 쿼리를 한번에 날려 조회하기 때문에 프록시 객체를 사용하는 것이 아닌 실제 객체를 사용하는 것을 확인 할 수 있다.


- 스프링 데이터 JPA @EntityGraph 사용

 

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

- @EntityGraph를 사용하게 되면 JPQL를 통해 fetch join을 별도로 작성하지 않아도, fetch join을 하고 싶은 엔티티를 attributePaths에 작성해주면 스프링 데이터 JPA에 의해 알아서 join을 한 쿼리를 날리게 된다.


@EntityGraph(attributePaths = {"team"})
List<Member> findEntityGraphByUsername(@Param("username") String username);
...
List<Member> members = memberRepository.findEntityGraphByUsername("member1");
...

- 추가로 위와 같이 @EntityGraph와 조건을 섞어서 사용할 수 있다.

- 위의 코드는 @EntityGraph를 통해 team을 fetch join함과 동시에 username을 파라미터 바인딩 하여 원하는 username을 조회하는 메서드이다.

- 스프링 데이터 JPA는 메서드를 통해 쿼리를 작성해주기 때문에 JPQL이 별도로 없어도 username에 파라미터 바인딩을 하고 싶다면 @Param을 통해 해당 필드에 값을 바인딩 해줄 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

출처 : 인프런 - 김영한(실전! 스프링 데이터 JPA)

728x90