본문 바로가기

JPA

3월 6일 JPA 주문조회 V5

JPA에서 DTO직접 조회 , 컬렉션 조회 최적화

 

V4에 문제였던 쿼리 n+1 문제 개선

 

@GetMapping("/api/v5/orders")

public List<orderQueryDto> ordersV5(){

 return orderQuertRepository.findAllByDto_Optimization();

}

 

1.order 가져오기

public List<orderQueryDto> findORders(){

 return em.createQuery(

 "select new jpabook~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();

}

 

2.orderItem 가져오기 V5 (v4에 n+1 해결)

public List<orderQueryDto> findAllByDto_Oprimization(){

 List<orderQuertyDto> result = findOrders();

 //일단 Order를 가져온다.

 

 List<Long> orderIds = result.stream()

 .map(o -> o.getOrderId())

 .collect(collectors.toList());

//가져온 order의 ID들을 List로 뽑아내기

 

List<orderItemQueryDto> orderItems = em.createQuery(

 "select new jpabook~orderItemQueryDto(oi.order.id , i.name , oi.orderPrice , oi.count)" +

 "from orderItem oi" +

 "join oi.item i" +

 "where oi.order.id in :orderIIds ", orderItemQuertDto.class)

.setParameter("orderIds" , orderIds)

.getResultList();

//가져온 orderIds(collection)을 IN절 뒤에 파라미터로 넣으면 In절에 값이 한번에 다 들어가게 된다.

}

 

Map<Long , List<orderItemQuertDto>> orderItemMap = orderItems.stream()

.collect(collectors.groupingBy(orderItemQuery::getOrderId)) //자바의 메소드 참조

-orderItems를 map으로 변경

-getOrderId를 키값으로 List값을 Value값으로 사용 리스트를 반환한다.

 

result.forEach(o -> o.setOrderItems(orderItemMap.get(o.getOrderId())));

result를 forEach를 적용하여 map과 일치하는 id값의 List로 각 order에 넣어준다.

메모리 단계로 가져와서 분배하는것이 핵심

 

in을 이요한 쿼리를 1번만 실행, 그 값을 map으로 바꾸어 각 order에 set해주어 return

order가져올때 1번 , OrderItem가져올때 1번 총 2번 쿼리가 나가게 된다.

'JPA' 카테고리의 다른 글

3월 6일 JPA API 개발 고급 정리  (0) 2023.03.06
3월 6일 JPA 주문조회 V6  (0) 2023.03.06
3월 3일 JPA 주문조회 v4  (0) 2023.03.03
2월 27일 주문조회 V3.1  (0) 2023.02.27
2월 27일 JPA 주문조회 V3  (0) 2023.02.27