3까지는 엔티티를 조회해서, 엔티티를 dto로 변환했고, 이번에는 바로 dto로 조회
package jpabook.jpashop.repository;
import jpabook.jpashop.domain.Address;
import jpabook.jpashop.domain.Order;
import jpabook.jpashop.domain.OrderStatus;
import lombok.Data;
import java.time.LocalDateTime;
@Data
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;
}
}
@GetMapping("/api/v4/simple-orders")
public List<OrderSimpleQueryDto> ordersV4() {
return orderRepository.findOrderDtos();
}
@Data
static class SimpleOrderDto {
private Long orderId;
private String name;
private LocalDateTime orderDate; //주문시간
private OrderStatus orderStatus;
private Address address;
public SimpleOrderDto(Order order) {
orderId = order.getId();
name = order.getMember().getName(); //Lazy 초기화
orderDate = order.getOrderDate();
orderStatus = order.getStatus();
address = order.getMember().getAddress(); //Lazy 초기화
}
}
public List<OrderSimpleQueryDto> findOrderDtos() {
return em.createQuery(
"select new jpabook.jpashop.repository.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();
}
v4의 결과는 v3와 동일하지만
select 쿼리를 보면 v3보다 원하는 결과에 맞는 것만 select 되어서 나온다.
직접 쿼리를 짰기 때문이다.
v3은 페치 조인이어서 select를 많이 하기 때문에 v4보다는 네트워크를 더 많이 쓴다.
v4와 v3은 둘 간에 우열을 가리기 어렵다. (trade-off 잇음)
v3은 내부의 원하는 것만 fetch로 튜닝
v3는 쿼리를 sql짜듯이 jpa로 가져온 것이다. 화면엔 사용할 수 있지만 재사용성이 떨어진다.
v3은 많은 api가 사용할 수 있음. 원하는 dto로 바꿔서 재사용
v3는 로직 재활용 안되지만, 성능최적화