본문 바로가기

Advance I/Springboot & JPA

22.05.13

상품 도메인 개발

구현 기능

  • 상품 등록
  • 상품 목록 조회
  • 상품 수정

순서

  • 상품 엔티티 개발(비즈니스 로직 추가)
  • 상품 리포지토리 개발
  • 상품 서비스 개발
  • 상품 기능 테스트

상품 엔티티 개발(비즈니스 로직 추가) 

상품 주문 -> Item.stockQuantity - OrderItem.count (재고 감소) (재고가 부족하면 예외 발생)

주문 취소 -> Item.stockQuantity + OrderItem.count (재고 증가)

엔티티의 필드 데이터를 변경하는 비지니스 로직은 엔티티 클래스 내에 구현한다.

getter/setter를 통해 클래스 밖에서 계산한 임의의 값을 직접 세팅하는 방법보다 더 객체지향적인 방법

상품 리포지토리/서비스 개발

@GerneratedValue 엔티티는 JPA로 저장(persist)하기 전까지 id 값이 없다.

save()

  • 엔티티의 id값이 없다 = 새로 생성한 객체이다. persist()
  • 엔티티의 id값이 있다. = 이미 데이터베이스에 저장된 엔티티를 수정한다. merge()?

주문 도메인 개발

구현 기능

  • 상품 주문
  • 주문 내역 조회
  • 주문 취소

순서

  • 주문 엔티티, 주문상품 엔티티 개발
  • 주문 리포지토리 개발
  • 주문 서비스 개발
  • 주문 검색 기능 개발
  • 주문 기능 테스트

주문, 주문상품 엔티티 개발

주문, 주문상품 생성은 비교적 복잡한 과정이기 때문에 주문 엔티티 내부에 별도의 생성 메서드를 만든다.

클라이언트가 모든 필드에 대한 setter를 따로따로 호출할 필요가 없어지고 유지보수에도 좋다.

주문 엔티티

//==생성 메서드==//
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;
}

 

  • public static XXX createXXX(Field...){ ... } : 객체를 생성하는 메서드이므로 클래스명으로 바로 호출할 수 있는 static 메서드로 정의한다. 주문 회원(Member), 배송정보(Delivery), 주문상품(OrderItem)을 받아서 실제 주문 엔티티를 생성한다.
  • cancel() : 주문 상태(OrderStatus)를 취소로 변경하고 주문상품(OrderItem)에 주문 취소를 알린다. 만약 이미 배송을 완료한 상품(DeliveryStatus.COMP)이면 주문을 취소하지 못하도록 예외를 발생시킨다.
  • getTotalPrice() : 주문 시 사용한 전체 주문 가격을 조회한다. 전체 주문 가격을 알려면 각각의 주문상품 가격을 알아야 한다. 로직을 보면 연관된 주문상품들의 가격을 조회해서 더한 값을 반환한다. (실무에서는 주로 주문에 전체 주문 가격 필드를 두고 역정규화 한다.)

주문상품 엔티티

//==생성 메서드==//
public static OrderItem createOrderItem(Item item, int orderPrice, int count) {
    OrderItem orderItem = new OrderItem();
    orderItem.setItem(item);
    orderItem.setOrderPrice(orderPrice);
    orderItem.setCount(count);
    
    item.removeStock(count);
    return orderItem;
}

/** 주문 취소 */
public void cancel() {
    getItem().addStock(count);
}

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

 

  • cancel() : getItem().addStock(count) 를 호출해서 취소한 주문 수량만큼 상품의 재고를 증가시킨다.
  • getTotalPrice() : 주문 가격에 수량을 곱한 값을 반환한다.

'Advance I > Springboot & JPA' 카테고리의 다른 글

22.05.17  (0) 2022.05.17
22.05.14  (0) 2022.05.14
22.05.11  (0) 2022.05.11
22.05.10  (0) 2022.05.10
22.05.09 :: 실전! 스프링 부트와 JPA 활용  (0) 2022.05.09