@EntityGraph

김건우·2022년 12월 3일
0

Spring Data JPA

목록 보기
3/11
post-thumbnail

Spring Data JPA[EntityGraph]

@EntityGraph를 사용하면 여러개의 배열로 fetch join이 가능하다.
@EntityGraph(attributePaths = {"item","item2","item3",.......}
여러개일 경우 배열로 {"item" , "item2""item3",..} 이런식으로 작성이 가능하다.

EntityGraph란?

연관관계가 있는 엔티티를 조회할 경우 지연로딩이 설정되어 있다면 연관관계에서 종속된 엔티티는 쿼리 실행시 select 되지 않고 proxy객체 를 만들어 엔티티가 적용시킨다
그 후 해당 proxy 객체를 호출할 때마다 그때 그때 select 쿼리가 실행된다
위 같은 연관관계가 지연 로딩으로 되어있을 경우 fetch 조인을 사용하여 여러 번의 쿼리를 한 번에 해결할 수 있다.

전에 연관관계가 Lazy로 되어있는 엔티티를 함께 조회해서 올때 fetch join @Query안에 쿼리문을 직접 사용했었다.

// TeamRepository.java
@Query("SELECT distinct t FROM Team t JOIN FETCH t.members")
public List<Team> findAllWithMembersUsingFetchJoin();

이 기능을 @EntityGraph라는 어노테이션을 사용함으로서 fecth join기능을 사용 할 수 있다.

Member (team과 manyToOne관계 [지연로딩 설정] )

@Entity
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED) // 기본생성자를 만들어 주는 기능
public class Member extends BaseEntity{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "member_id")
    private Long Id;
    private String username;
    private int age;

    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "team_id")
    private Team team;


    public Member( String username) {
        this.username = username;
    }

}

Team(member와 OneToMany관계 [defalut Lazy] )

@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Team {

    @Id
    @GeneratedValue
    @Column(name = "team_id")
    private Long id;
    private String name;

    @OneToMany(mappedBy = "team", cascade = ALL)
    private List<Member> members = new ArrayList<>();

}

Fetchjoin, @Entitygraph를 사용하지 않은 findAll() 메서드를 사용시

memberRespository.findAll() 쿼리 실행 결과 🔽

위처럼 지연로딩설정 후 fetchjoin이나 @EntityGraph를 사용하지 않았을 시 member 객체만 조회하고 team 객체는 프락시 객체가 대체되어 들어간다.

select쿼리가 한 번만 이루어진다. Member 객체 내에서 Team 객체에 접근하기 전까지는 Team에 대한 쿼리를 수행하지 않기 때문이고 FetchType.LAZY가 하는일이기도 하다.

public interface MemberRepository extends JpaRepository<Member,Long> ,MemberRepositoryCustom{

      @Override
      @EntityGraph(attributePaths = {"team"},type = EntityGraph.EntityGraphType.LOAD) 
      List<Member> findAll();

    }

@EntityGraph를 사용한 memberRespository.findAll() 쿼리 실행 결과 🔽

위와 같은 @Entitygraph의 사용은 member엔티티의 연관관계가있는 Team(지연로딩관계) 를 EAGER로 패치하여 조회한다. 왜냐하면 attributePaths = {"team"} 속성에 team이 들어가기 때문이다.

EntityGraph.EntityGraphType.FETCH 와 EntityGraph.EntityGraphType.LOAD

  1. FETCH: entity graph에 명시한 attribute는 EAGER로 패치하고, 나머지 attribute는 LAZY로 패치
  2. LOAD: entity graph에 명시한 attribute는 EAGER로 패치하고, 나머지 attribute는 entity에 명시한 fetch type이나 디폴트 FetchType으로 패치

@OneToMany는 LAZY, @ManyToOne은 EAGER가 디폴트이다.

@EntityGraph가 가장 강점을 발휘하는 순간의 네이밍메소드랑 fetchJoin을 동시에 할 수있는 순간이다

//메서드 이름으로 쿼리에서 특히 편리하다.
@EntityGraph(attributePaths = {"team"})
List<Member> findByUsername(String username)
profile
Live the moment for the moment.

0개의 댓글