1 분 소요

1
2
3
4
5
//controller
@GetMapping("/api/v4/orders")  
public List<OrderQueryDto> ordersV4() {  
    return orderQueryRepository.findOrderQueryDtos();  
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// repository
@Repository  
@RequiredArgsConstructor  
public class OrderQueryRepository {  
  
    private final EntityManager em;  
  
    public List<OrderQueryDto> findOrderQueryDtos() {  
        List<OrderQueryDto> result = findOrders();  
  
        result.forEach(o -> {  
           List<OrderItemQueryDto> orderItems = findOrderItems(o.getOrderId());  
           o.setOrderItems(orderItems);  
        });  
        return result;  
    }  
    public List<OrderQueryDto> findOrders() {  
        return em.createQuery(  
                        "select new jpabook.jpashop.repository.order.query.OrderQueryDto(o.id, m.name, o.orderDate, o.status, d.address) from Order o" +  
                                " join o.member m" +  
                                " join o.delivery d", OrderQueryDto.class)  
                .getResultList();  
  
    }  
    private List<OrderItemQueryDto> findOrderItems(Long orderId) {  
        return 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 = :orderId", OrderItemQueryDto.class)  
                .setParameter("orderId", orderId)  
                .getResultList();  
  
    }  
  
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// OrderQueryDto
@Data  
public class OrderQueryDto {  
    private Long orderId;  
    private String name;  
    private LocalDateTime orderDate;  
    private OrderStatus orderStatus;  
    private Address address;  
    private List<OrderItemQueryDto> orderItems;  
  
    public OrderQueryDto(Long orderId, String name, LocalDateTime orderDate, OrderStatus orderStatus, Address address) {  
        this.orderId = orderId;  
        this.name = name;  
        this.orderDate = orderDate;  
        this.orderStatus = orderStatus;  
        this.address = address;  
    }  
}

// OrderItemQueryDto
@Data  
public class OrderItemQueryDto {  
    @JsonIgnore  
    private Long orderId;  
    private String itemName;  
    private int orderPrice;  
    private int count;  
  
    public OrderItemQueryDto(Long orderId, String itemName, int orderPrice, int count) {  
        this.orderId = orderId;  
        this.itemName = itemName;  
        this.orderPrice = orderPrice;  
        this.count = count;  
    }  
}

  • Query: 루트 1번, 컬랙션 N번 실행
  • ToOne(N:1, 1:1) 관계를 먼저 조회하고, ToMany(1:N)관계는 각각 별도로 처리했다.
    • 이런 방식을 선택한 이유는 다음과 같다.
    • ToOne 관계는 조인해도 row수가 증가하지 않는다.
    • ToMany(1:N)관계는 조인하면 row수가 증가한다.
  • row수가 증가하지 않는 ToOne관계는 조인으로 최적화 하기 쉬우므로 한번에 조회하고, ToMany 관계는 최적화 하기 어려우므로 findOrderItems()같은 별도의 메서드로 조회했다.

나 스스로 N+1 을 만들어 버린거다. ㅎㅎ;

태그: ,

카테고리:

업데이트:

댓글남기기