티스토리 뷰
반응형
이전에 ToOne관계는 fetch join 이후 ToMany는 지연 로딩으로 가져오는 것까지 봤다.
다음으로는 지연로딩으로 가져오는 과정에서 결국 query가 많이 날아가기 때문에,
ToMany또한 쿼리를 만들어서 해주는 방법이 있다.
public List<OrderQueryDto> findOrderQueryDtos() {
List<OrderQueryDto> results = findOrders();
results.forEach(o -> {
List<OrderItemQueryDto> orderItems = findOrderItems(o.getOrderId());
o.setOrderItems(orderItems);
});
return results;
}
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();
}
private 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();
}
다음처럼 findOrders를 가지고 ToOne관계를 먼저 만들어준 뒤에
다시 results를 roof를 돌리면서 orderItems를 다시 findOrderItems를 이용해서 채워주는 방식이다.
이렇게 하면 이전보다 쿼리가 더 적게 나가게 된다.
조금더 최적화하는 방법은 Map을 이용해 맵으로 변형을 한뒤 메모리에서 매칭을 해서 반환해주는 것이다.
public List<OrderQueryDto> findAllByDto_optimization() {
List<OrderQueryDto> results = findOrders();
Map<Long, List<OrderItemQueryDto>> orderItemMap = findOrderItemMap(toOrderIds(results));
results.forEach(o -> o.setOrderItems(orderItemMap.get(o.getOrderId())));
return results;
}
private List<Long> toOrderIds(List<OrderQueryDto> results){
return results.stream()
.map(o -> o.getOrderId())
.collect(Collectors.toList());
}
private Map<Long, List<OrderItemQueryDto>> findOrderItemMap(List<Long> orderIds){
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();
return orderItems.stream()
.collect(Collectors.groupingBy(OrderItemQueryDto -> OrderItemQueryDto.getOrderId()));
}
마지막으로는 ToMany관계가 없는 DTO를 만들어주는 것이다.
하지만 이 방법의 경우에는 orderId가 중복으로 들어가기 때문에 페이징을 할때 원하는 기준으로 정렬이 되어 있지 않다.
public List<OrderFlatDto> findAllByDto_flat() {
return em.createQuery(
"select new jpabook.jpashop.repository.order.qeury.OrderFlatDto(o.id, m.name, o.orderDate, o.status, d.address, i.name, oi.orderprice, oi.count)"+
" from Order o"+
" join o.member m"+
" join o.delivery d"+
" join o.orderItems oi"+
" join oi.item i", OrderFlatDto.class
).getResultList();
}
@Data
@AllArgsConstructor
@EqualsAndHashCode(of = "orderId")
public class OrderFlatDto {
private Long orderId;
private String name;
private LocalDateTime orderDate;
private OrderStatus orderStatus;
private Address address;
private String itemName;
private int orderPrice;
private int count;
}
728x90
반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- OS
- K8S
- zookeeper
- Data Engineering
- KAFKA
- spring boot
- frontend
- 프론트엔드
- broker
- Container
- cs
- NextJS
- apache
- consumer
- API
- backend
- feign client
- 리액트
- Java
- React
- Firebase
- Linux
- JPA
- centos
- spring
- Front
- apache kafka
- Producer
- caching
- rhel
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함
250x250