/**
* V3. 엔티티를 조회해서 DTO로 변환(fetch join 사용O)
* - fetch join으로 쿼리 1번 호출
* 참고: fetch join에 대한 자세한 내용은 JPA 기본편 참고(정말 중요함)
*/
@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;
}
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
)을 사용해서 쿼리 1번에 조회order ➡️ member
, order ➡️ delivery
는 이미 조회 된 상태 이므로 지연로딩 X➡️ 실행하면 V2를 실행했을 때와 같은 JSON 형식이 반환됨!
그러나 쿼리 형식이 다름!!
➡️ V2는 총 5번의 쿼리가 실행됐다
➡️ 그러나 V3는 단 1번의 쿼리만 실행됐다!!
/**
* V4. JPA에서 DTO로 바로 조회
* - 쿼리1번 호출
* - select 절에서 원하는 데이터만 선택해서 조회
*/
@GetMapping("/api/v4/simple-orders")
public List<OrderSimpleQueryDto> ordersV4() {
return orderSimpleQueryRepository.findOrderDtos();
}
../repository.order.simplequery.OrderSimpleQueryRepository.java
생성
package jpabook.jpashop.repository.order.simplequery;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import java.util.List;
@Repository
@RequiredArgsConstructor
public class OrderSimpleQueryRepository {
private final EntityManager em;
public List<OrderSimpleQueryDto> findOrderDtos() {
return em.createQuery(
"select new jpabook.jpashop.repository.order.simplequery.OrderSimpleQueryDto(o.id, m.name, o.orderDate, o.status, d.address)" +
" from Order o" +
" join o.member m" +
" join o.delivery d", OrderSimpleQueryDto.class)
.getResultList();
}
}
../repository.order.simplequery.OrderSimpleQueryDto.java
생성
package jpabook.jpashop.repository.order.simplequery;
import jpabook.jpashop.domain.Address;
import jpabook.jpashop.domain.Order;
import jpabook.jpashop.domain.OrderStatus;
import lombok.Data;
import java.time.LocalDateTime;
public class OrderSimpleQueryDto {
private Long orderId;
private String name;
private LocalDateTime orderDate;
private OrderStatus orderStatus;
private Address address;
public OrderSimpleQueryDto(Long orderId, String name, LocalDateTime
orderDate, OrderStatus orderStatus, Address address) {
this.orderId = orderId;
this.name = name;
this.orderDate = orderDate;
this.orderStatus = orderStatus;
this.address = address;
}
}
new
명령어를 사용해서 JPQL의 결과를 DTO로 즉시 변환SELECT
절에서 원하는 데이터를 직접 선택하므로 DB 애플리케이션 네트워크 용량 최적화(생각보다 미비함)쿼리 방식 선택 권장 순서
1️⃣ 우선 엔티티를 DTO로 변환하는 방법을 선택한다.
2️⃣ 필요하면 페치 조인으로 성능을 최적화 한다. 대부분의 성능 이슈가 해결된다🙂
3️⃣ 그래도 안되면 DTO로 직접 조회하는 방법을 사용한다.
4️⃣ 최후의 방법은 JPA가 제공하는 네이티브 SQL이나 스프링 JDBC Template을 사용해서 SQL을 직접 사용한다.
페치 조인의 세계란,,,,^_^