@EntityGraph를 사용하면 여러개의 배열로 fetch join이 가능하다.
@EntityGraph(attributePaths = {"item","item2","item3",.......}
여러개일 경우 배열로 {"item" , "item2""item3",..} 이런식으로 작성이 가능하다.
연관관계가 있는 엔티티를 조회할 경우 지연로딩이 설정되어 있다면 연관관계에서 종속된 엔티티는 쿼리 실행시 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기능을 사용 할 수 있다.
@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;
}
}
@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<>();
}
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이 들어가기 때문이다.
@OneToMany는 LAZY, @ManyToOne은 EAGER가 디폴트이다.
//메서드 이름으로 쿼리에서 특히 편리하다.
@EntityGraph(attributePaths = {"team"})
List<Member> findByUsername(String username)