21.05.03 00:16 작성
·
1.7K
0
안녕하세요 영한님!
좋은 강의 너무너무 잘 듣고 있습니다!
다름이 아니라 JPA와 Querydsl을 공부하던 중 궁금한 점이 생겨 이렇게 질문을 드립니다.
OneToMany 관계에서는 N+1 문제를 해결하기 위해 fetch join을 사용해 자식 엔티티도 모두 함께 가져오는 것으로 배웠습니다.
만약 아래처럼 하나의 엔티티와 자식 엔티티, 자식 엔티티의 자식 엔티티가 모두 OneToMany 관계인 경우 최상위 엔티티를 가져올 때 한꺼번에 모든 자식 엔티티를 가져올 수 있는 방법이 있는지 여쭤보고 싶습니다..!
@Entity
public class Forest{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "forest_id")
private Long id;
@OneToMany(mappedBy = "forest")
private List<Tree> trees= new ArrayList<>();
}
@Entity
public class Tree{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "tree_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "forest_id")
private Forest forest;
@OneToMany(mappedBy = "tree", cascade = CascadeType.ALL)
private List<Leaf> leaves= new ArrayList<>();
}
@Entity
public class Leaf{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "leaf_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "Tree_id")
private Tree tree;
}
위 코드를 기준으로 제가 원하는 것은 모든 Forest을 가져올 때, Forest의 자식인 Tree와 Tree의 자식인 Leaf를 함께 가져오는 것인데,
처음엔 단순히 fetch join을 두번 사용하면 될 것이라고 생각했습니다.
따라서 코드를 다음과 같이 작성했습니다.
public List<Forest> findAllFetch() {
return queryFactory
.selectFrom(forest)
.leftJoin(forest.trees, tree).fetchJoin()
.leftJoin(tree.leaves).fetchJoin()
.fetch();
}
하지만 위 코드처럼 두개 이상의 OneToMany 관계에서 fetch join을 여러번 사용하면 MultipleBagFetchException이 발생했습니다.
찾아보니 JPQL에서는 xToMany에서는 일반적으로 fetch join은 한번만 허용된다고 하더라구요...
따라서 제가 생각한 해결책은 위 과정을 2번의 쿼리로 나누어 실행시키는 방법이었습니다.
public List<Forest> findAllFetch() {
List<Forest> result = queryFactory
.selectFrom(forest).distinct()
.leftJoin(forest.trees).fetchJoin()
.fetch();
List<Long> selectedIds = result.stream()
.map(Forest::getId)
.collect(Collectors.toList());
queryFactory
.selectFrom(tree).distinct()
.leftJoin(tree.leaves).fetchJoin()
.where(tree.forest.id.in(selectedIds ))
.fetch();
return result ;
}
혹시 위 코드보다 더 나은 방법이 있는지 아니면 한번의 쿼리로 모든 자식 엔티티를 받아올 수 있는 방법이 있는지 궁금합니다.
답변 1
0
2021. 05. 03. 18:53
안녕하세요. 김싸피님
한줄로 답변을 드릴 수 있으면 좋겠지만, 이 부분을 이해하려면 여러가지 성능 최적화 개념을 이해하셔야 합니다.
관련해서 실전! 스프링 부트와 JPA 활용2편 강의에서 상황별로 다양한 최적화 방법을 자세히 설명드립니다.
감사합니다.
2021. 05. 03. 23:52
답변 감사합니다!!
따흐흑....ㅠㅠ 완강하고 얼른 활용 2편을 수강해야 할것 같네요.