Spring boot

스프링 부트 - 주문 및 주문 상품 Entity 개발 학습내용

방구석 대학생 2021. 1. 16. 21:46

"인프런 - 실전! 스프링 부트와 JPA 활용1 강의를 듣고 작성한 글 입니다."

www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-JPA-%ED%99%9C%EC%9A%A9-1#

 

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발 - 인프런

실무에 가까운 예제로, 스프링 부트와 JPA를 활용해서 웹 애플리케이션을 설계하고 개발합니다. 이 과정을 통해 스프링 부트와 JPA를 실무에서 어떻게 활용해야 하는지 이해할 수 있습니다. 초급

www.inflearn.com

 

 

사실상 이번 예제 에서 가장 중요한 도메인이다.

주문 도메인은 비즈니스 로직이 얽혀서 돌아가는 걸 JPA 나 Entity 를 통해 알 수 있는 도메인이다.

 

* 주문 도메인 개발 순서

- 주문 Entity, 주문 상품 Entity 개발

- 주문 Repository 개발

- 주문 Service 개발

- 주문 검색 기능 개발

- 주문 기능 테스트

 

우선 Order 도메인 클래스에 핵심 비즈니스 로직을 작성한다.

주문 생성과정은 굉장히 복잡하다

Order 뿐만 아니라, OrderItem, Delivery 와 같은 연관관계의 정보들이 들어있기 때문에 꽤 복잡하다.

그렇기에 이와 같은 복잡한 생성과정은 생성 메소드를 만들어서 활용하는 것이 좋다.

 

- Order.java

@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();

//== 연관관계 편의 메소드
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;
}

 

생성 메소드를 작성해주는 것이 중요한 이유?

앞으로 뭔가 생성해야 하는 지점을 변경해야 할 일이 생기면 위의 메소드 하나만 변경시켜 주면 된다.

 

 

* 기타 비즈니스 로직 메소드

주문 취소 및 주문 전체가격 조회

- Order.java

// 비즈니스 로직
/* 주문 취소 */
public void cancel() {
    if(delivery.getStatus() == DeliveryStatus.CAMP){
        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;
}

- OrderItem.java

// 비즈니스 로직
public void cancel(){
    getItem().addStock(count); // 상품이 취소 되었으므로 재고를 다시 주문수량 만큼 늘려준다.
}

// 조회 로직
/* 주문 상품 전체 가격조회 */
public int getTotalPrice(){
    return getOrderPrice() * getCount();
}