오봉이와 함께하는 개발 블로그

JPA 2 - 주문 조회V2 : 엔티티를 DTO로 변환 본문

BE/JPA

JPA 2 - 주문 조회V2 : 엔티티를 DTO로 변환

오봉봉이 2022. 9. 5. 21:57
728x90

주문 조회 V2: 엔티티를 DTO로 변환

    @GetMapping("/api/v1/orders")
    public List<OrderDto> ordersV2() {
        List<Order> orders = orderRepository.findAllByCriteria(new OrderSearch());
        List<OrderDto> result = orders.stream()
                .map(o -> new OrderDto(o))
                .collect(toList());

        return result;
    }

OrderApiController에 추가

@Data
static class OrderDto {
    private Long orderId;
    private String name;
    private LocalDateTime orderDate;
    private OrderStatus orderStatus;
    private Address address;
    private List<OrderItem> orderItems;

    public OrderDto(Order order) {
        orderId = order.getId();
        name = order.getMember().getName();
        orderDate = order.getOrderDate();
        orderStatus = order.getStatus();
        address = order.getDelivery().getAddress();
        order.getOrderItems().stream().forEach(o -> o.getItem().getName());
        orderItem = order.getOrderItems();
    }
}

위 코드로 하면 OrderItem에 대한 DTO는 없기 때문에 엔티티를 그대로 조회하게 된다.
아래 코드와 같이 연관관계가 걸린 엔티티도 DTO를 만들어서 조회하자.
단, Address와 같은 ValueObject는 예외다.

@Data
    static class OrderDto {
        private Long orderId;
        private String name;
        private LocalDateTime orderDate;
        private OrderStatus orderStatus;
        private Address address;
        private List<OrderItemDto> orderItems;

        public OrderDto(Order order) {
            orderId = order.getId();
            name = order.getMember().getName();
            orderDate = order.getOrderDate();
            orderStatus = order.getStatus();
            address = order.getDelivery().getAddress();
            orderItems = order.getOrderItems().stream()
                    .map(orderItem -> new OrderItemDto(orderItem))
                    .collect(toList());
        }
    }
    @Data
    static class OrderItemDto {
        private String itemName;//상품 명
        private int orderPrice; //주문 가격
        private int count; //주문 수량

        public OrderItemDto(OrderItem orderItem) {
            itemName = orderItem.getItem().getName();
            orderPrice = orderItem.getOrderPrice();
            count = orderItem.getCount();
        }
    }
  • 위 코드는 지연 로딩으로 인해 너무 많은 SQL이 실행된다.
  • SQL 실행 수
    • Order : 1번
    • member, address : N번(Order 조회 수 만큼)
    • orderItem : N번(Order 조회 수 만큼)
    • item : N번(orderItem 조회 수 만큼)

참고로 지연 로딩은 영속성 컨텍스트에 있으면 영속성 컨텍스트에 있는 엔티티를 사용하고 없으면 SQL을 실행한다. 따라서 같은 영속성 컨텍스트에서 이미 로딩한 회원 엔티티를 추가로 조회하면 SQL을 실행하지 않는다.

인프런 김영한 지식공유자님 강의 - 실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
728x90
Comments