JPA
Join vs Fetch Join
혀눅짱
2023. 10. 4. 17:06
차이점
일반 조인
- Fetch Join과 달리 연관 Entity에 Join을 걸어도 실제 쿼리에서 SELECT 하는 Entity는 JPQL에서 조회하는 주체가 되는 Entity만 조회하여 영속화
- 조회의 주체가 되는 Entity만 SELECT 해서 영속화하기 때문에 데이터는 필요하지 않지만 연관 Entity가 검색조건에는 필요한 경우에 주로 사용됨
Fetch 조인
- 조회의 주체가 되는 Entity 이외에 Fetch Join이 걸린 연관 Entity도 함께 SELECT 하여 모두 영속화
- Fetch Join이 걸린 Entity 모두 영속화하기 때문에 FetchType이 Lazy인 Entity를 참조하더라도
이미 영속성 컨텍스트에 들어있기 때문에 따로 쿼리가 실행되지 않은 채로 N+1문제가 해결됨
이제 조인 예시를 보자 먼저 일반적인 조인이다.
public List<Order> test(String name){
List<Order> orders = em.createQuery(
"select o " +
"from Order o " +
"join o.member m " +
"where m.name =:name"
, Order.class)
.setParameter("name",name)
.getResultList();
return orders;
}
특정 유저의 주문을 검색조건으로 조인했을때 발생하는 쿼리를 출력해보면
Order엔티티의 정보만 가져온다(실제 주체가 되는 Entitiy) .
이 다음 fetch join으로 바꿔보도록 한다.
public List<Order> test(String name){
List<Order> orders = em.createQuery(
"select o " +
"from Order o " +
"join fetch o.member m " +
"where m.name =:name"
, Order.class)
.setParameter("name",name)
.getResultList();
return orders;
}
그 결과 쿼리에서 Order 엔티티 뿐만 아니라 Member 엔티티의 정보 역시 출력한다.
조인과 fetch 조인을 비교해보았을때 당연히 쿼리에서 연관엔티티 까지 긁어오는 fetch 조인이 더 간편해보였다. 왜냐면 이럴경우 lazy 로딩에 의한 추가적인 쿼리가 발생하지 않으니까.. (사실 뭐 즉시로딩이든 지연로딩이든 n+1 쿼리는 발생함)
근데 결국 fetch join 은 연관엔티티도 영속성 컨텍스트에 영속화하기 때문에 굳이 연관 엔티티를 쓸일이 없고 검색조건에만 쓰이게 된다면 일반 조인을 쓰는게 적합하다고 한다.
그리고 또 조금 가물가물하긴 한데 또 fetch join이 jpa의 성능이슈를 해결하는 무조건 적인 답은 아닌 걸로 기억이 난다. 일대다 컬렉션관계에서 페이징이 필요하면 오히려 엄청난 성능이슈를 일으킬 수 도 있고 ..
복습을 계속해보면서 성능 최적화에 대한 것들을 정리하도록 해야겠다.