JPA를 사용해서 연관관계가 설정된 데이터를 조회할 때 일반적으로 LAZY
기법으로 조회를 한다. 그렇기에 조인을 사용할 때 일명 n+1
문제가 발생할 수 있는데 이를 해결하기 위해 fetch join
을 사용할 수 있다. 하지만 fetch join
을 사용하기 위해서는 JPQL
을 사용해야만 하기 때문에 JPARepository
인터페이스가 기본적으로 제공하는 기본 메서드들에는 사용할 수 가 없다. 그럴때 사용할 수 있는 것이 바로 Entity Graph
이다.
간단히 말해서 조회 쿼리(1)를 날렸을 때 결과 데이터들의 개수만큼 조인 쿼리(N)가 더 발생하는 문제이다. 이는 당연히 프로그램의 성능에 영향을 주기 때문에 방치해서는 안되는 문제이다.
@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(exclude = "team")
public class Member {
@Id
@GeneratedValue
@Column(name = "member_id")
private Long id;
private String username;
private int age;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id")
private Team team;
...Getter, Setter 생략
@Entity
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(exclude = "members")
public class Team {
@Id @GeneratedValue
@Column(name = "team_id")
private Long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
Member를 조회하면서 연관된 Team의 정보도 같이 필요할 때 fetch join
이나 EntityGraph
를 사용한다.
//공통 메서드 오버라이드
@Override
@EntityGraph(attributePaths = {"team"})
List<Member> findAll();
MemberRepository에 공통 메서드를 오버라이딩하면서 @EntityGraph
어노테이션을 붙여주면 된다. 어노테이션에 연관관계 필드명을 넣어주는 것을 잊지말자.
사용결과는 fetch join
과 동일하게 최초 Member 조회 시 조인이 같이 나가며 단 한번의 쿼리로 모든 정보를 조회하게 된다. 당연히 Member의 정보만 필요할 때는 사용해서는 안되며 Member의 연관 Team의 정보에 접근하고자 할 때만 사용해야 한다.