728x90
Controller

OrderRepositoryV5
public List<OrderQueryDto> findAllByDtoOptimization() {
List<OrderQueryDto> result = findOrders();
//이전꺼는 루프를 도는 단점이 있었음
Collection<Long> orderIds = toOrderIds(result);
List<OrderItemQueryDto> orderItems = em.createQuery(
"select new jpabook.jpashop.repository.order.query.OrderItemQueryDto(oi.order.id,i.name,oi.orderPrice,oi.count)"
+" from OrderItem oi"
+" join oi.item i"
+" where oi.order.id in :orderIds",OrderItemQueryDto.class
)
.setParameter("orderIds",orderIds)
.getResultList();
//메모리 맵에 올려놓고 매핑한다.
Map<Long,List<OrderItemQueryDto>> orderItemMap = findOrderItemMap(orderItems);
result.forEach(o -> o.setOrderItems(orderItemMap.get(o.getOrderId())));
//쿼리가 총 2번 나간다.
return result;
}
private Map<Long, List<OrderItemQueryDto>> findOrderItemMap(List<OrderItemQueryDto> orderItems) {
return orderItems.stream()
.collect(Collectors.groupingBy(orderItemQueryDto -> orderItemQueryDto.getOrderId()));
}
private List<Long> toOrderIds(List<OrderQueryDto> result) {
return result.stream()
.map(o -> o.getOrderId())
.collect(Collectors.toList());
}
- Query: 루트 1번, 컬렉션 1번
- ToOne 관계들을 먼저 조회하고, 여기서 얻은 식별자 orderId로 ToMany 관계인 OrderItem을 한꺼번에 조회
- MAP을 사용해서 매칭 성능 향상(O(1))
- In 쿼리를 사용하여 한번에 여러 개의 데이터를 조회한다.
- Stream 객체를 활용하여 Map에 담아 result에 List로 반환해서 출력한다.
- 쿼리 총 2번만 실행된다.
728x90
'실전! 스프링 부트와 JPA 활용2(API 개발과 성능 최적화)' 카테고리의 다른 글
| Ch04. API 개발 고급(컬렉션 조회 최적화) - API 개발 고급 정리 (0) | 2021.12.21 |
|---|---|
| Ch04. API 개발 고급(컬렉션 조회 최적화) - 주문 조회 V6(JPA에서 DTO로 직접 조회, 플랫 데이터 최적화) (0) | 2021.12.21 |
| Ch04. API 개발 고급(컬렉션 조회 최적화) - 주문 조회 V4(JPA에서 DTO 직접 조회) (0) | 2021.12.21 |
| Ch04. API 개발 고급(컬렉션 조회 최적화) - 주문 조회 V3.1(Entity를 DTO로 변환 (페이징과 한계 돌파)) (0) | 2021.12.21 |
| Ch04. API 개발 고급(컬렉션 조회 최적화) - 주문 조회 V3(Entity -> DTO로 변환 ( 페치 조인 최적화)) (0) | 2021.12.21 |