스프링데이터 + JPA 112

15. Dto 직접조회 컬렉션 최적화

지금은 컬렉션도 각각 Dto로 조회해오면서, batch가 안 먹히게 되었다. (정확히 등록된 엔티티를 조회해와야만 되는 듯 하다(fetch 한것 등)) 그래서 지금 컬렉션은 ToOne이 아니라서 row 뻥튀기를 일으키게 하지 않기 위해 따로 넣어줬다. 그래서 이렇게 OrderItem을 넣어줄 때마다 또 그 OrderItem을 조회해주는 쿼리가 n번 나가게 되었다. 이제는 저 OrderItem 조회하는 걸 쿼리를 한번만 나가게끔 만들 것이다. @GetMapping("/api/v5/orders") public List ordersV5(){ return orderQueryRepository.findAllByDto_optimization(); } public List findAllByDto_optimizatio..

14. 컬렉션 Dto로 직접 조회

화면에 fit한 데이터들 찾는 용도의 Repository는 따로 패키지및 클래스를 만든다. @GetMapping("/api/v4/orders") public List ordersV4(){ return orderQueryRepository.findOrderQueryDtos(); } public List findOrderQueryDtos() { List result = findOrders(); result.forEach((o)->{ List orderItems = findOrderItems(o.getOrderId()); o.setOrderItems(orderItems); }); return result; } 여러 메소드로 나눠서 조회했다. ToOne?과 ToMany는 따로 조회했다. 이유는 new 오퍼레이션..

13. 컬렉션 페이징 한계돌파

컬렉션 패치조인은 결국 JPA는 데이터를 일단 다 가지고 와 메모리에서 페이징을 하기 때문에, 데이터가 많을 경우 out of memory도 날 수 있고 생각보다 굉장히 위험하다. 지금부터 페이징 + 컬렉션 엔티티 함께 조회하는 효율적인 방법을 알아보겠다. 먼저, ToOne관계는(즉 나에게 1인) 모두 join fetch한다. row수를 증가시키지 않는다. 그래서 페이징 해도 상관이 없다. 그 다음 컬렉션은 그냥 LAZY 로딩인 상태로 둔다. 여기서 뭔가 작업을 해 둘거다. 일단은, ToOne 관계는 그냥 join fetch해서 가져온다. @GetMapping("/api/v3.1/orders") public List ordersV3_page(){ List orders = orderRepository.fi..

12. 컬렉션 -> 엔티티 join fetch 최적화

그냥 join fetch 해서 가져올 거다. @GetMapping("/api/v3/orders") public List ordersV3(){ List orders = orderRepository.findAllWithItem(); return orders.stream() .map(o-> new OrderDto(o)) .collect(Collectors.toList()); } public List findAllWithItem() { return em.createQuery("select o from Order o" + " join fetch o.member m" + " join fetch o.delivery d" + " join fetch o.orderItems oi" + " join fetch oi.item..

11. 컬렉션 엔티티를 Dto로

@GetMapping("/api/v2/orders") public List ordersV2(){ List orders = orderRepository.findAllString(new OrderSearch()); return orders.stream() .map(o-> new OrderDto(o)) .collect(Collectors.toList()); } 변환 작업을 거쳐야 한다. OrderDto라는 것을 만들었다. 그런데, Order에 있는 OrderItems 또한 엔티티이다. 그래서 이것 또한 변환작업을 해야 한다. @Getter static class OrderDto{ private Long orderId; private String name; private LocalDateTime orderDat..

10. 컬렉션 조회 최적화

지금까지는 컬렉션 조회해오지는 않았음. 그런 것들의 경우 그냥 join fetch로 해결 가능 컬렉션 조회는 일대다 조회가 됨. 뭐 테이블도 대충 이런 느낌임. 일단 단계적으로 할거임. 마찬가지로 엔티티 직접 노출 먼저 할거임. @GetMapping("/api/v1/orders") public List ordersV1(){ List result = orderRepository.findAllString(new OrderSearch()); for (Order order : result) { order.getMember().getName(); order.getDelivery().getAddress(); List orderItems = order.getOrderItems(); for (OrderItem orde..

9. 바로 Dto로 받기

@GetMapping("/api/v4/simple-orders") public List ordersV4(){ return orderRepository.findOrderDtos(); } 바로 리포지토리에서 Dto로 가져오는 걸 정의하는 거다. public List findOrderDtos() { return em.createQuery("select new jpabook.jpashop.repository.OrderSimpleQueryDto(o.id, m.name, o.orderDate, o.status, d.address)" + " from Order o" + " join o.member m" + " join o.delivery d", OrderSimpleQueryDto.class) .getResultLis..

8. fetch join 최적화

@GetMapping("/api/v3/simple-orders") public List orderV3(){ List orders = orderRepository.findAllWithMemberDelivery(); List result = orders.stream() .map(o-> new SimpleOrderDto(o)) .collect(Collectors.toList()); return result; } 똑같은 데, 저 DB에서 가져오는 걸 findAllWithMemberDelivery()라는 걸 만들어서 가져올 거다. 메소드 이름이 거지같긴 한데, 보통은 주문이면 member와 delivery 가져와야 한다 이정도로 어느 정도 자주 쓰는 객체 그래프가 정해져 있기 때문에 그냥 findAll이라고 이름..

6. 지연로딩과 조회성능 최적화

주문(Order) + 배송정보(Delivery) + 회원(Member) 조회하는 API를 만들거임. 점차적으로 성능을 향상시킬거임. xToOne은 기본이 즉시로딩이라, 명시적으로 LAZY로딩으로 해 줘야 함. 일단은, 이런 연관관계 무시하고, @GetMapping("/api/v1/simple-orders") public List ordersV1(){ List all = orderRepository.findAllString(new OrderSearch()); return all; } 이렇게 하면 무한루프에 빠짐. 왜냐하면, @Entity @Table(name = "orders") @Getter @NoArgsConstructor(access = AccessLevel.PUBLIC) public class Or..