> For the complete documentation index, see [llms.txt](https://heunnajo.gitbook.io/jpa-2-api/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://heunnajo.gitbook.io/jpa-2-api/3.-api/v3-dto-fetch-join.md).

# 간단한 주문 조회 V3: 엔티티를 DTO로 변환 - fetch join 최적화

V1, V2에서 발생했던 N+1 문제들을 fetch join을 이용해서 해결하고, 성능을 최적화한다!

V3 API

```java
@GetMapping("/api/v3/simple-orders")
public List<SimpleOrderDto> ordersV3() {
    List<Order> orders = orderRepository.findAllWithMemberDelivery();
    List<SimpleOrderDto> result = orders.stream()
            .map(o -> new SimpleOrderDto(o))
            .collect(toList());
    return result;
}
```

OrderRepository 추가 코드 : JPQL 직접 작성

```java
public List<Order> findAllWithMemberDelivery() {
        return em.createQuery(
                "select o from Order o" +
                "join fetch o.member m" +
                "join fetch o.delivery d", Order.class
        ).getResultList();
}
```

**fetch join**\
기술적으로는 join을 사용하지만 JPA 명령어 "fetch"를 사용함으로써\
join fetch 로 Order를 조회할 때 member도 함께 조회한다!

**한번의 쿼리로 Order, Member, Delivery 조인 후 select 절에 다 넣고 한번 에 가져온다!**\
**Order, Member, Delivery가 지연로딩이지만 무시하고, 프록시 객체가 아니라 진짜 객체 가져온다!**

V2, V3 결과는 동일하지만 쿼리를 확인해보면\
V2 : 5개\
**V3 : 1개**

**쿼리문 확인**\
Order, Member, Delivery 모두 inner join을 해서 select문에 한번에 넣는다.\
Order, Member, Delivery 각각의 row들을 JPA가 연관관계에 의해 자동으로 셋팅해준다!

**정리**\
기본적으로 모두 지연로딩으로 하고, 필요한 것들만 fetch join으로 DB에서 한번에 가져온다!\
대부분의 성능 문제가 해결된다!

실무에서 발생하는 90%의 문제가 N+1문제이고, fetch join으로 해결 가능!\
그렇기 때문에 fetch join에 대해 정확하게 알고 있어야 한다!\
실무에서 정말 자주 사용하는 기법이다!⭐️⭐️⭐️⭐️⭐️
