이전 코드에서 더 최적화를 해서 쿼리 한방으로 해결되는 방법을 알아보겠습니다.

주문 조회 V6: JPA에서 DTO 직접 조회, 플랫 데이터 최적화

@GetMapping("/api/v6/orders")
public List<OrderFlatDto> ordersV6() {
    return orderQueryRepository.findAllByDto_flat();
}
@Data
public class OrderFlatDto { //...1

    private Long orderId;
    private String name;
    private LocalDateTime orderDate;
    private OrderStatus orderStatus;
    private Address address;
    private String itemName;
    private int orderPrice;
    private int count;

    public OrderFlatDto(Long orderId, String name, LocalDateTime orderDate, OrderStatus orderStatus, Address address, String itemName, int orderPrice, int count) {
        this.orderId = orderId;
        this.name = name;
        this.orderDate = orderDate;
        this.orderStatus = orderStatus;
        this.address = address;
        this.itemName = itemName;
        this.orderPrice = orderPrice;
        this.count = count;
    }

}
  1. Order 와 OrderItem 을 조인하고 OrderItem 와 Item 을 조인해서 모든 데이터를 한 번에 다 가져오기 위한 DTO 입니다.

    DB 에서 데이터를 한 줄로 플랫하게 가져올 수 있도록 데이터 구조를 맞춰야 합니다.

public List<OrderFlatDto> findAllByDto_flat() {
    return em.createQuery(
            "select new jpabook.jpashop.repository.order.query.OrderFlatDto(o.id, m.name, o.orderDate, o.status, d.address, i.name, oi.orderPrice, oi.count)" +
                    " from Order o" +
                    " join o.member m" +
                    " join o.delivery d" +
                    " join o.orderItems oi" +
                    " join oi.item i", OrderFlatDto.class)
            .getResultList();
}

실행을 해봅시다.

[
    {
        "orderId": 4,
        "name": "userA",
        "orderDate": "2024-04-22T10:36:12.922416",
        "orderStatus": "ORDER",
        "address": {
            "city": "서울",
            "street": "1",
            "zipcode": "1111"
        },
        "itemName": "JPA1 BOOK",
        "orderPrice": 10000,
        "count": 1
    },
    {
        "orderId": 4,
        "name": "userA",
        "orderDate": "2024-04-22T10:36:12.922416",
        "orderStatus": "ORDER",
        "address": {
            "city": "서울",
            "street": "1",
            "zipcode": "1111"
        },
        "itemName": "JPA2 BOOK",
        "orderPrice": 20000,
        "count": 2
    },
    {
        "orderId": 11,
        "name": "userB",
        "orderDate": "2024-04-22T10:36:13.043211",
        "orderStatus": "ORDER",
        "address": {
            "city": "진주",
            "street": "2",
            "zipcode": "2222"
        },
        "itemName": "SPRING1 BOOK",
        "orderPrice": 20000,
        "count": 3
    },
    {
        "orderId": 11,
        "name": "userB",
        "orderDate": "2024-04-22T10:36:13.043211",
        "orderStatus": "ORDER",
        "address": {
            "city": "진주",
            "street": "2",
            "zipcode": "2222"
        },
        "itemName": "SPRING2 BOOK",
        "orderPrice": 40000,
        "count": 4
    }
]

데이터가 중복이 돼서 응답하고 있습니다.

실제 JPA 가 만들어주는 쿼리를 봅시다.

Untitled

쿼리를 직접 실행하면 총 로우가 4개 나옵니다.