양방향 연관관계일 경우 무한루프를 방지하기 위해 필드 레벨에서 어노테이션 추가
Order 엔티티에서 Member 엔티티 다대일 연관관계
@Entity
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED) //생성 메소드만 통일되게 사용하도록 생성자 제한
@Table(name = "orders")
public class Order {
@Id @GeneratedValue
@Column(name = "order_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY) //relation owner
@JoinColumn(name = "member_id")
private Member member;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL) //relation target
private List<OrderItem> orderItems = new ArrayList<>();
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) //relation owner
@JoinColumn(name = "delivery_id")
private Delivery delivery;
private LocalDateTime orderDate;
@Enumerated(EnumType.STRING) //변경가능성을 고려하여 string으로 지정
private OrderStatus status; //enum: ORDER, CANCEL
//==연관관계 편의 메소드==//
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 totalPrice;
}
}
@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
@Column(name = "member_id")
private Long id;
@NotEmpty
private String name;
@Embedded //임베디드 내장타입 사용
private Address address;
@JsonIgnore
@OneToMany(mappedBy = "member") //relation target
private List<Order> orders = new ArrayList<>();
}