인프런 커뮤니티 질문&답변

리자몽님의 프로필 이미지
리자몽

작성한 질문수

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

order저장 시 OrderStatus.ERROR일 때 Item의 stockQuantity를 감소시키지 않게 하기 질문이요

작성

·

267

·

수정됨

0

Order가 저장할 때 OrderStatus.ERROR 일 때는 Order만 db에 저장되고

Item의 재고(stockQuantity)는 감소가 안되게 하고 싶습니다.

즉, Order는 OrderStatus.ERROR 여부와 상관없이 저장이 되고

OrderStatus.ERROR일때만 Item의 재고(stockQuantity)는 감소가 안되게 하고 싶습니다.

(ERROR니까 재고가 감소안되게 하려고합니다)

 

저는 주문(order)하다가 에러가 발생하면 throw로 Exception을 던지지 않고

OrderStatus만 ERROR로 변경해 주려고 합니다.

즉 ERROR 발생했을때 OrderStatus의 값을 order.setStatus(OrderStatus.ERROR)를 통해 에러를 발생시키지만 주문자체는 db에 저장되고

Item의 재고(stockQuantity)를 줄여주지 않으려고합니다.

물론 ERROR가 발생하지 않고 정상적으로 실행이 되면 Item의 재고도 정삭적으로 줄어 들겠죠

 

다음은 Order 엔터티입니다. 강의와 조금 다르게 TimeStapmed를 상속받았는데 질문과는 상관없습니다.

@Entity
@Table(name = "orders")
@Getter @Setter
@NoArgsConstructor
public class Order extends TimeStamped{

    @Id @GeneratedValue
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_id")
    private Member member;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    List<OrderItem> orderItems = new ArrayList<>();
   
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Delivery delivery;
    
    @Enumerated(EnumType.STRING)
    private OrderStatus status;

    private long orderTotalPrice;

    public void addOrderItem(OrderItem orderItem){
        orderItems.add(orderItem);
        orderItem.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.orderTotalPrice += orderItem.getTotalPrice();
            order.addOrderItem(orderItem);
        }
        order.setStatus(OrderStatus.CREATED);

        return order;
    }
}

그래서 제가 해준 방법은 우선 특정 조건일 때 setStatus(OrderStatus.ERROR) 으로 에러를 발생시킵니다. (길어져서 코드에는 안적었는데 디버깅상 전혀 문제가 없습니다. 그냥 특정조건일 때 에러 발생시키는 겁니다.)

그리고 Order 엔터티에 있는

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 을

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.DETACH) 로 수정한다음에

OrderService에서 order를 save한 후 OrderStatus.ERROR 일때만 flush를 발동 시켰는데

orderRepository.save(order);

if (order.getStatus() == OrderStatus.ERROR){
    orderRepository.flush();
}

orderItem만 저장이 안되고 Item의 stockQuantity는 줄어드는군요

그래서 OrderItem에 있는

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "item_id")
private Item item;

위 코드에 cascade = CascadeType.DETACH 를 추가해도 소용이 없더군요

 

어떻게하면

order는 OrderStatus의 ERROR 여부와 상관없이 order는 저장이 되고

OrderStatus.ERROR 일때만 Item의 stockQuantity가 저장이 안되게 할 수 있을까요?

 

혹시몰라서 OrderItem과 Item의 코드도 올립니다.

OrderItem엔터티의 코드

@Entity
@Getter @Setter
@NoArgsConstructor
public class OrderItem {

    @Id @GeneratedValue
    @Column(name = "order_item_id")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "item_id")
    private Item item;

    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "order_id")
    private Order order;

    private Integer orderPrice;

    private Integer quantity;

// ... createOrderItem ...
// ... getTotalPrice ...
}

 

Item엔터티의 코드입니다.

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "dtype") 
@Getter
@NoArgsConstructor
@AllArgsConstructor
public abstract class Item {

    @Id @GeneratedValue
    @Column(name = "item_id")
    private Long id;

    private String name;

    private Integer price;

    private Integer stockQuantity;

    public Item(String name, Integer price,Integer stockQuantity){
        this.name = name;
        this.price = price;
        this.stockQuantity = stockQuantity;
    }

    public void removeStock(Integer quantity) {
        Integer restStock = this.stockQuantity - quantity;
        if(restStock < 0) {
            throw new EApplicationException(ErrorCode.NOT_ENOUGH_STOCK, String.format("Out of Stock"));
        }
        this.stockQuantity = restStock;
    }
}

 

감사합니다.

답변 1

0

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 리자몽님

기본적으로 엔티티의 값을 변경하지 않고 문제를 해결해야 합니다.

엔티티의 값을 변경한다는 것은 이미 비즈니스 로직이 그렇게 동작해야 한다는 것을 뜻합니다.

따라서 OrderStatus.ERROR인 경우에는 재고를 유지하도록 애플리케이션 코드를 변경하시면 됩니다.

(재고 감소 코드를 호출하지 않으면 됩니다.)

감사합니다.

리자몽님의 프로필 이미지
리자몽

작성한 질문수

질문하기