toOne(ManyToOne, OneToOne) 관계 같은 경우는 페치 조인을 통해서 쉽게 문제를 해결할 수 있었습니다.
근데 컬렌션 조회는 일대다(OneToMany) 조회가 됩니다.
예를 들어, DB 입장에서 one 쪽 데이터가 1개가 있고 many 쪽 데이터가 3개가 있을 때 조인을 하면 row가 3줄로 늘어나죠.
이런 경우를 뻥튀기가 된다고 표현하는데 일대다는 최적화 하기가 어렵습니다. 고민해야 될 포인트가 많이 있기 때문입니다.
주문내역에서 주문한 상품 정보를 추가로 조회하겠습니다. 기존 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
},
...
]