주문 조회 V4: JPA에서 DTO 직접 조회
JPA에서 DTO 직접 조회
OrderApiController 내부에 만든 OrderDto를 재사용하지 않고 새로 만든 이유
Repository에서 Controller의 클래스를 참조하게 될 경우 Repository가 Controller를 참조하면 순환이 생겨버린다‼️(Controller->Repository 순방향)
그래서 Repository > order > query 하위에 아래와 같이 따로 빼내서 만든다!
OrderItemQueryDto //OrderItemDTO
OrderQueryDto //OrderDTO //orderId 없어도 되지만 일단 만듦. 화면에 렌더링하는 용도의 데이터라서 나중에 안 쓰려면 @JsonIgnore 처리해주면 됨.
OrderQueryRepository : EntityManager로 쿼리 작성
OrderQueryRepository 쿼리 작성⭐️⭐️⭐️⭐️⭐️ 1. findOrders() //Order 조회 : Member와 Delivery 조인해서 OrderDTO 생성해서 반환(OrderQueryDto) ⭐️ 이때 new 연산자로 컬렉션을 바로 받지 못한다! DB는 플랫하게 한 row씩 데이터가 들어가기 때문이다. 그래서 컬렉션은 따로 처리해주어야한다. 2. findOrderItems(Long orderId) // OrderItem 조회 : OrderItem 과 Item 조인해서 OrderItemDTO 생성해서 반환(OrderItemQueryDto) 3. findOrderQueryDtos() //메인 메서드. 핵심 로직⭐️⭐️⭐️⭐️⭐️⭐️ : OrderDTO에 List<OrderItemDTO> 컬렉션을 넣는다! 2에서 조회한 OrderItemDTO를 foreach문으로 컬렉션에 넣는다!!!
=>하지만 이코드에서 역시 N+1문제가 발생한다!!!!! findOrderQueryDtos > findOrders() 1번,//주문 1번 foreach문에서 데이터 갯수 N개 만큼 N번//주문 상품 갯수만큼(여기서는 N = 2번)
findOrders() JPQL select절에서 new 연산자로 DTO 생성해서 반환 시, select 절에 new 연산자로 바로 컬렉션을 넣을 수 없다‼️ (참고)일반 SQL 쓸 때 생각해보면 된다. (SQL처럼 쓰는데 new로 DTO를 할 뿐.) =>플랫하게 한줄밖에 못 넣는다. OrderItems는 일대다 관계로 데이터가 증가하기 때문에 select절에 new로 바로 못 넣는다‼️ 컬렉션 List<OrderItem>만 제외하고 new로 DTO 생성(컬렉션은 따로 넣어주는 처리!)⭐️⭐⭐️
2. findOrderItems(Long orderId) OrderItem과 Item은 다대일(ManyToOne) 관계이므로 조인해도 된다!!!
3. 핵심로직 : OrderItemDTO를 OrderDTO에 List<OrderItemDTO> 컬렉션에 넣기 findOrderItems로 조회한 List<OrderItemDTO>를 foreach문으로 하나하나 OrderDTO의 List<OrderItemDTO>에 넣는다!!!!!!!!!
Last updated