인프런 커뮤니티 질문&답변

하하하님의 프로필 이미지

작성한 질문수

실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화

주문 조회 V3.1: 엔티티를 DTO로 변환 - 페이징과 한계 돌파

v3.1 쿼리 최적화

작성

·

288

0

안녕하세요 선생님!

v3.1에서 쿼리 실행 결과 order 조회-> orderItem 조회 -> item 이 조회됩니다.

저는 OrderItem 안에 item이 Lazy 로딩이니 페치 조인으로 가지고 오고 싶어서 다음과 같은 로직을 작성해보았습니다.  

@GetMapping("/api/v3.2/orders")
public List<OrderDto> ordersV3_page2(
@RequestParam(value = "offset", defaultValue = "0") int offset,
@RequestParam(value = "limit", defaultValue = "100") int limit
) {
List<Order> orders = orderRepository.findWithMemberDelivery(offset, limit);
List<Long> ids = orders.stream().map(order -> order.getId()).collect(toList());
List<OrderItem> orderItems = orderQueryRepository.findOrderDto(ids);
return orders.stream()
.map(order -> new OrderDto(order, orderItems))
.collect(toList());
}
public List<OrderItem> findOrderDto(List<Long> ids) {
return em.createQuery(
"select oi from OrderItem oi join fetch oi.item where oi.order.id in :ids", OrderItem.class)
.setParameter("ids", ids)
.getResultList();
}
public OrderDto(Order order, List<OrderItem> orderItems) {
orderId = order.getId();
name = order.getMember().getName();
orderDate = order.getOrderDate();
orderStatus = order.getStatus();
address = order.getDelivery().getAddress();
this.orderItems = orderItems.stream().map(OrderItemDto::new).collect(toList());
}

이와 같이 로직을 작성 하고 결과를 확인하니 

 

 

위와 같이 모든 Item이 조회되었습니다.

 

혹시 fetch join 이 문제 일까 싶어서 fetch join 을 제외하고  실행하더라도 동일한 결과가 나왔습니다.

 

fetch join을 빼고 실행하면 강의에서 나온 것과 동일하게 쿼리가 실행되지만 결과값은 다른 것을 확인했습니다. -> batch_fetch_size를 사용했을때만 동일한 쿼리가 실행됨.(결과값은 다름)

batch_fetch_size 사용 시 단순히 in 쿼리로 결과를 가져오는 것이 아니라 지연로딩을 생각해서 결과값을 가져온다고 생각하면 되는걸까요? 동일한 쿼리가 실행되는데도 결과 값이 다르게 나오는게 이해가 잘안됩니다 ㅠㅠ

 

 

 

답변 1

1

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 김진욱님

작성하신 findOrderDto에서 모든 OrderItem들을 다 조회해버리는데요.

그것을 다음 로직에서 그대로 각각 다 넣어버리니, 각각 모든 OrderItem을 가지게 됩니다.

OrderDto를 만드는 단계에서 자신의 것만 가지도록 분류해주시던가 해야할 것 같아요.

 

public OrderDto(Order order, List<OrderItem> orderItems) {

   orderId = order.getId();

   name = order.getMember().getName();

   orderDate = order.getOrderDate();

   orderStatus = order.getStatus();

   address = order.getDelivery().getAddress();

   this.orderItems = orderItems.stream().map(OrderItemDto::new).collect(toList());

}

감사합니다.