toOne(ManyToOne, OneToOne) 관계 같은 경우는 페치 조인을 통해서 쉽게 문제를 해결할 수 있었습니다.

근데 컬렌션 조회는 일대다(OneToMany) 조회가 됩니다.

예를 들어, DB 입장에서 one 쪽 데이터가 1개가 있고 many 쪽 데이터가 3개가 있을 때 조인을 하면 row가 3줄로 늘어나죠.

이런 경우를 뻥튀기가 된다고 표현하는데 일대다는 최적화 하기가 어렵습니다. 고민해야 될 포인트가 많이 있기 때문입니다.

주문 조회 V1: 엔티티 직접 노출

주문내역에서 주문한 상품 정보를 추가로 조회하겠습니다. 기존 API 에 Order 기준으로 컬렉션인 OrderItem 과 Item 을 추가하는 것이죠.

Order 안에는 OrderItem 가 리스트로 되어 있고 Item 이름 등을 찾기 위해서 OrderItem 에서 Item 을 찾아 들어가야 합니다.

주문한 내역과 주문 안에 있는 상품명 등을 어떻게 출력하는지 만들어보겠습니다.

@RestController
@RequiredArgsConstructor
public class OrderApiController {

    private final OrderRepository orderRepository;

    @GetMapping("/api/v1/orders")
    public List<Order> ordersV1() {
        List<Order> all = orderRepository.findAllByString(new OrderSearch());
        for (Order order : all) {
            order.getMember().getName();
            order.getDelivery().getAddress();
            List<OrderItem> orderItems = order.getOrderItems();
            orderItems.stream().forEach(o -> o.getItem().getName());
        }
        return all;
    }

}

OrderSimpleApiController 에서 만들었던 ordersV1() 과 거의 동일합니다. orderItems 를 다 가져와서 스트림을 통해 item 을 강제 지연로딩 시키는 부분만 추가가 됐죠.

실행을 해봅시다.

orderItems 배열 안에 item 정보가 있는 것을 확인할 수 있습니다.

[
    {
        "id": 4,
        "member": {
            "id": 1,
            "name": "userA",
            "address": {
                "city": "서울",
                "street": "1",
                "zipcode": "1111"
            }
        },
        "orderItems": [
            {
                "id": 6,
                "item": {
                    "id": 2,
                    "name": "JPA1 BOOK",
                    "price": 10000,
                    "stockQuantity": 99,
                    "categories": null,
                    "author": null,
                    "isbn": null
                },
                "orderPrice": 10000,
                "count": 1,
                "totalPrice": 10000
            },
            {
                "id": 7,
                "item": {
                    "id": 3,
                    "name": "JPA2 BOOK",
                    "price": 20000,
                    "stockQuantity": 98,
                    "categories": null,
                    "author": null,
                    "isbn": null
                },
                "orderPrice": 20000,
                "count": 2,
                "totalPrice": 40000
            }
        ],
        "delivery": {
            "id": 5,
            "address": {
                "city": "서울",
                "street": "1",
                "zipcode": "1111"
            },
            "status": null
        },
        "orderDate": "2024-04-13T22:00:35.087381",
        "status": "ORDER",
        "totalPrice": 50000
    },
    ...
]