ManyToOne
이나OneToOne
관계 조인 >Fetch Join
OneToMany
조회 >Collection 조회
DB에서 조회 할 때, Many만큼 줄이 증가하므로, 최적화하기 힘들다.
(하지만, 엔티티를 직접 노출하면 안된다.)
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();
//OrderItem이 리스트로 되어 있음
package jpabook.jpashop.api;
import jpabook.jpashop.domain.Order;
import jpabook.jpashop.domain.OrderItem;
import jpabook.jpashop.repository.OrderRepository;
import jpabook.jpashop.repository.OrderSearch;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequiredArgsConstructor
public class OrderApiController {
private final OrderRepository orderRepository;
@GetMapping("/api/v1/orders")
public List<Order> ordersV1(){
List<Order> all = orderRepository.findAllByString(new OrderSearch());
for (Order order : all) { // iter + tab > for문 만들 수 있음
order.getMember().getName();
order.getDelivery().getAddress();
List<OrderItem> orderItems = order.getOrderItems();
orderItems.stream().forEach(o->o.getItem().getName());
/** Item명 초기화 시키는 것
* OrderItem에는 상품명 객체 참조로 있는데,
* LAZY이므로 강제초기화 시켜줘야함
*/
}
return all;
}
}
**양방형관계는 꼭 @JsonIgnore를 걸어줘서 끊어주기..!
@GetMapping("/api/v2/orders")
public List<OrderDto> ordersV2(){
List<Order> orders = orderRepository.findAllByString(new OrderSearch());
List<OrderDto> collect = orders.stream()
.map(o->new OrderDto(o))
.collect(Collectors.toList());
return collect;
}
@Getter
static class OrderDto{
private Long orderId;
private String name;
private LocalDateTime orderDate;
private OrderStatus orderStatus;
private Address address;
private List<OrderItem> orderItems;
public OrderDto(Order order){
orderId = order.getId();
name = order.getMember().getName();
orderDate= order.getOrderDate();
orderStatus=order.getStatus();
address=order.getDelivery().getAddress();
orderItems= order.getOrderItems();
}
}
!! DTO를 사용할지라도, 그대로 entity를 외부에 노출해서는 안됨 !!
-> Map을 이용해 묶기, 필요한 정보만 노출해야함.
@Getter
static class OrderDto{
private Long orderId;
private String name;
private LocalDateTime orderDate;
private OrderStatus orderStatus;
private Address address;
private List<OrderItemDto> orderItems;
public OrderDto(Order order){
orderId = order.getId();
name = order.getMember().getName();
orderDate= order.getOrderDate();
orderStatus=order.getStatus();
address=order.getDelivery().getAddress();
orderItems= order.getOrderItems().stream()
.map(orderItem -> new OrderItemDto(orderItem))
.collect(Collectors.toList()); //엔티티이므로, NULL로 반환
}
}
@Getter
static class OrderItemDto{
private String itemName;
private int orderPrice;
private int count;
public OrderItemDto(OrderItem orderItem){
itemName = orderItem.getItem().getName();
orderPrice = orderItem.getOrderPrice();
count = orderItem.getCount();
}
}
이 방식으로 필요한 정보들만 가져올 수 있으나, 지연 로딩으로 너무 많은 SQL 실행
SQL 실행 수