OneToMany 연관관계 조회 & 컬렉션 조회 V1 & V2
OneToMany 연관관계에서는 속성들이 컬렉션(List 등)이므로 이를 고려해서 연관관계 조회를 해야 합니다
V1, V2 모두 최적의 방법이 아니기 때문에, 두 방법을 사용하는 것을 추천하지 않습니다. 해당 포스팅은 이런한 방법이 있으며, 어떠한 문제점이 발생하며, 문제점들의 해결방안을 제시하기 위함 입니다.
V1: 엔티티
@GetMapping("api/v1/collection-orders")
public List<Order> ordersV1() {
List<Order> all = orderRepository.findAllByCriteria(new OrderSearch());
for (Order order : all) {
//영속성 컨텍스트에 추가해주기
order.getId();
order.getMember().getUsername(); //Lazy 강제 초기화
order.getOrderDate();
order.getDelivery().getAddress(); //Lazy 강제 초기화
List<OrderItem> orderItems = order.getOrderItems();
orderItems.stream()
.forEach(o -> o.getItem().getName()); //Lazy 강제 초기화
}
return all;
}
ManyToOne, OneToOne일때와 똑같은 문제 발생과 해결 방법도 비슷합니다. 여전히 절대 실무에서는 사용하면 안되는 방법입니다.
V2: DTO
API
@GetMapping("api/v2/collection-orders")
private Result ordersV2() {
List<Order> orders = orderRepository.findAllByCriteria(new OrderSearch());
List<OrderCollectionDTO> orderDTOS = orders.stream()
.map(o -> new OrderCollectionDTO(o))
.collect(Collectors.toList());
return new Result(orderDTOS);
/**
* 지연 로딩 때문에 최악의 경우 총 1+5N의 쿼리문이 처리됩니다:
* member , address 2N번(order 조회 수 만큼)
* orderItem N번(order 조회 수 만큼)
* item 2N번(orderItem 조회 수 만큼)(order.getItem().getName())
*/
}
DTO
@Data
static class OrderCollectionDTO {
private Long orderId;
private String username; //주문자 이름
private LocalDateTime orderDate;
private OrderStatus orderStatus;
private Address address; //배송지
private List<OrderItemDTO> orderItems;
/**
* Response를 반환 할때 엔티티 반환 X
* 그 뜻은, DTO에서도 엔티티 반환 X
* 그러므로, OrderItem도 DTO로 변환해서 반환
* 또한, OrderItem도 DTO로 변환하면 클라이언트가 원하는 값만 보낼 수 있음
*/
public OrderCollectionDTO(Order order) {
this.orderId = order.getId();
this.username = order.getMember().getUsername();
this.orderDate = order.getOrderDate();
this.orderStatus = order.getStatus();
this.address = order.getDelivery().getAddress();
this.orderItems = order.getOrderItems().stream()
.map((o) -> new OrderItemDTO(o))
.collect(Collectors.toList());
}
}
@Data
static class OrderItemDTO {
private String itemName;
private int orderPrice;
private int count;
public OrderItemDTO(OrderItem orderItem) {
this.itemName = orderItem.getItem().getName();
this.orderPrice = orderItem.getOrderPrice();
this.count = orderItem.getCount();
}
}
@Data
@AllArgsConstructor
static class Result<T>{
public T data;
}
ManyToOne, OneToOne일때와 비슷합니다. 하지만, 추가로 고려해야 될 상황이 있습니다. DTO로 반환한다는 뜻은 클라이언트에 절대로 엔티티 자체를 보내지 않아햐 합니다. 그러므로, orderItems를 반환 할때도, List을 그대로 반환하는 것이 아니라, OrderItemDTO라는 새로운 DTO를 추가로 생성해서, OrderItem -> OrderItemDTO로 변환 후, List를 반환해야 합니다.
V2의 경우 여전히 1+N의 문제가 발생하는데, OrderItem -> OrderItemDTO로 변환하는 과정에서 추가로 쿼리문을 실행하게 됩니다. 그렇기 때문에, ManyToOne, OneToOne일때는 1+2N 이였지만, OneToMany에서는 1+5N의 쿼리가 발생하게 됩니다. 이러한 문제점 해결 및 최적화는 V3에서 다루도록 하겠습니다.
Author And Source
이 문제에 관하여(OneToMany 연관관계 조회 & 컬렉션 조회 V1 & V2), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@k_ms1998/OneToMany-연관관계-조회-컬렉션-조회-V1-V2저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)