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

me님의 프로필 이미지

작성한 질문수

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

간단한 주문 조회 V2: 엔티티를 DTO로 변환

14:06초 질문있어요

23.01.26 14:36 작성

·

280

0

14:06초에 왜 delivery만 select하는 쿼리가 나갔는지 모르겠어요

@GetMapping("/api/v2/simple-orders")
public List<SimpleOrderDto> ordersV2() {
    List<Order> orders = orderRepository.findAllByString(new OrderSearch());
    List<SimpleOrderDto> result = orders.stream()
            .map(o -> new SimpleOrderDto(o))
            .collect(Collectors.toList());
    return result;
}
@Data
static class SimpleOrderDto{
    private Long orderId;
    private String name;
    private LocalDateTime orderDate;
    private OrderStatus orderStatus;
    private Address address;

    public SimpleOrderDto(Order order) {
       orderId = order.getId();
       name = order.getMember().getName(); //Lazy 강제 초기화
       orderDate = order.getOrderDate();
       orderStatus = order.getStatus();
       address = order.getDelivery().getAddress(); //Lazy 강제 초기화
    }
}

에서

List<Order> orders = orderRepository.findAllByString(new OrderSearch());

여기서 order 테이블 select 하는 쿼리 1번

List<SimpleOrderDto> result = orders.stream()
            .map(o -> new SimpleOrderDto(o))
            .collect(Collectors.toList());

public SimpleOrderDto(Order order) {
       orderId = order.getId();
       name = order.getMember().getName(); //Lazy 강제 초기화
       orderDate = order.getOrderDate();
       orderStatus = order.getStatus();
       address = order.getDelivery().getAddress(); //Lazy 강제 초기화
    }

여기서 member랑 address 함께 join하는 쿼리 2번 (order이 2개이며 fk가 다 달라서 영속성 컨텍스트에 있지 않음)

 

총 3번으로 n+1문제가 발생하여야 된다고 생각했는데 어디가 틀렸는지 모르겠어요

 

답변 1

0

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

2023. 01. 28. 17:22

안녕하세요. me님

여기는 EAGER 상황이어서 그렇습니다.

먼저 JPQL로 ORDER만 조회를 했습니다. JPA는 JPQL에 충실하게 동작하기 때문에 먼저 DB에서 Order만 조회합니다.

그런데 JPQL로 조회를 하고 보니 Order와 Delivery가 EAGER로 걸려있습니다. EAGER는 JPQL 반환 시점에 데이터를 다 불러와야 합니다. 그래서 추가로 Delivery에 대해서 다시 한번 조회를 하게 됩니다.

감사합니다.

 

me님의 프로필 이미지

작성한 질문수

질문하기