package jpabook.jpashop.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Entity
@Getter
@Setter
@Table(name = "orders")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Order {
@Id
@GeneratedValue
@Column(name = "order_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;
@OneToMany(mappedBy = "order",cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();
@OneToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL)
@JoinColumn(name="delivery_id")
private Delivery delivery;
private LocalDateTime orderDate;
@Enumerated(EnumType.STRING)
private OrderStatus status;
public void setMember(Member member) {
this.member = member;
member.getOrders().add(this);
}
public void addOrderItem(OrderItem orderItem) {
orderItems.add(orderItem);
orderItem.setOrder(this);
}
public void setDelivery(Delivery delivery) {
this.delivery=delivery;
delivery.setOrder(this);
}
//생성 메소드
public static Order createOrder(Member member, Delivery delivery, OrderItem... orderItems) {
Order order = new Order();
order.setMember(member);
order.setDelivery(delivery);
for (OrderItem orderItem : orderItems) {
order.addOrderItem(orderItem);
}
order.setStatus(OrderStatus.ORDER);
order.setOrderDate(LocalDateTime.now());
return order;
}
/**
* 주문취소
*/
public void cancel() {
if (delivery.getStatus() == DeliveryStatus.COMP) {
throw new IllegalStateException("이미 배송완료된 상품은 취소가 불가능합니다.");
}
this.setStatus(OrderStatus.CANCEL);
for (OrderItem orderItem : orderItems) {
orderItem.cancel();
}
}
//조회로직//
/**
* 전체 주문 가격 조회
*/
public int getTotalPrice(){
// int totalPrice = 0;
// for (OrderItem orderItem : orderItems) {
// totalPrice += orderItem.getTotalPrice();
// }
return orderItems.stream().mapToInt(OrderItem::getTotalPrice).sum();
}
}
order, member, delivery를 조회하고 싶을때
public List<Order> findAll() {
return em.createQuery(
"select o from Order o",Order.class).getResultList();
}
query문으로 order가 하나라고 가정했을때 order를 조회한 후 member, delivery에 접근한다면
n+1문제가 발생한다. 왜냐하면 order를 조회할때, order안에 있는 member를 접근할때, order안에 있는 delivery에 접근할때, 총 3번의 sql이 나가게 된다.
join fetch를 통한 한방쿼리를 날리면 서버와의 통신을 획기적으로 줄일 수 있다.
public List<Order> findAllWithMemberDelivery() {
return em.createQuery(
"select o from Order o"+
" join fetch o.member m "+
"join fetch o.delivery d ",Order.class).getResultList();
}
한번의 쿼리로 order, member, delivery를 모두 가져오기때문에 불필요한 서버와 DB간의 통신을 줄일 수 있다.