다중 주문 상품의 변경

22.10.29 20:32 작성 조회수 86

0

안녕하세요.

선생님의 조언 하나를 듣고 싶어서 글을 남깁니다.!

이는 여러 주문 상품에 관한 질문입니다.

코드리뷰에 관한 부분은 아니고 제가 생각하는 절차적인 부분에서 조언을 얻고싶습니다.

일단 주문을 전체 취소하지 않고 주문 내역 중 일부 상품을 삭제하고 상품을 등록하는 부분에 대해 고민을 하고 있습니다.

클라이언트에서 주문 상품에 대한 정보를 새롭게 전달해 주었을 때 이를 단순히 기존 Order에서 setOrderItem으로 저장하면 연관관계의 주인이 아니기 때문에 어떠한 변경도 없습니다.

그래서 기존 Order를 가져온 이후 getOrderItems()를 통해 삭제 및 등록을 진행했습니다.

//given
Order order = em.find(Order.class, 4L);
List<OrderItem> orderItems = order.getOrderItems();
List<Long> newOrderLineItemId = Arrays.asList(9L);
//when
//삭제
List<OrderItem> removeOrderLine = orderItems.stream()
        .filter(orderItem -> !newOrderLineItemId.contains(orderItem.getItem().getId()))
        .collect(Collectors.toList());
orderItems.removeIf(removeOrderLine::contains);

//등록
newOrderLineItemId.forEach( itemId -> {
    Item item = em.find(Item.class, itemId);
    OrderItem orderItem = OrderItem.createOrderItem(item, 10000, 2);
    orderItems.add(orderItem);
});

 

이러면 Order와 OrderItems 둘 다 영속 상태이기 때문에 변경 감지를 통해 OrderItems insert문이 전송되는 것 까지는 확인을 했습니다.

하지만 기존의 존재하던 상품의 삭제에 따라 OrderItems에 delete문을 전송하는 것은 확인하지 못했습니다.

그래서 뭘 놓쳤을까 고민하던 차 삭제되어야 할 OrderItems는 여전히 Order를 참조하고 있다는게 문제 같았습니다.

removeOrderLine.forEach(orderItem -> {
    orderItem.setOrder(null);
});

다음 코드를 넣고 실행했더니 다음과 같은 결과가 나왔습니다.

insert

into

order_item

(count, item_id, order_id, order_price, order_item_id)

values

(?, ?, ?, ?, ?)

2022-10-29 20:09:00.704 TRACE 7104 --- [ Test worker] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [INTEGER] - [2]

2022-10-29 20:09:00.704 TRACE 7104 --- [ Test worker] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [9]

2022-10-29 20:09:00.704 TRACE 7104 --- [ Test worker] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [BIGINT] - [null]

2022-10-29 20:09:00.704 TRACE 7104 --- [ Test worker] o.h.type.descriptor.sql.BasicBinder : binding parameter [4] as [INTEGER] - [10000]

2022-10-29 20:09:00.704 TRACE 7104 --- [ Test worker] o.h.type.descriptor.sql.BasicBinder : binding parameter [5] as [BIGINT] - [15]

2022-10-29 20:09:00.705 DEBUG 7104 --- [ Test worker] org.hibernate.SQL :

update

order_item

set

count=?,

item_id=?,

order_id=?,

order_price=?

where

order_item_id=?

2022-10-29 20:09:00.705 TRACE 7104 --- [ Test worker] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [INTEGER] - [1]

2022-10-29 20:09:00.705 TRACE 7104 --- [ Test worker] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [2]

2022-10-29 20:09:00.705 TRACE 7104 --- [ Test worker] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [BIGINT] - [null]

2022-10-29 20:09:00.705 TRACE 7104 --- [ Test worker] o.h.type.descriptor.sql.BasicBinder : binding parameter [4] as [INTEGER] - [10000]

2022-10-29 20:09:00.705 TRACE 7104 --- [ Test worker] o.h.type.descriptor.sql.BasicBinder : binding parameter [5] as [BIGINT] - [6]

2022-10-29 20:09:00.705 DEBUG 7104 --- [ Test worker] org.hibernate.SQL :

update

order_item

set

count=?,

item_id=?,

order_id=?,

order_price=?

where

order_item_id=?

2022-10-29 20:09:00.706 TRACE 7104 --- [ Test worker] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [INTEGER] - [2]

2022-10-29 20:09:00.706 TRACE 7104 --- [ Test worker] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [3]

2022-10-29 20:09:00.706 TRACE 7104 --- [ Test worker] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [BIGINT] - [null]

2022-10-29 20:09:00.706 TRACE 7104 --- [ Test worker] o.h.type.descriptor.sql.BasicBinder : binding parameter [4] as [INTEGER] - [20000]

2022-10-29 20:09:00.706 TRACE 7104 --- [ Test worker] o.h.type.descriptor.sql.BasicBinder : binding parameter [5] as [BIGINT] - [7]

 

아! 주입되는 값에대해 정리해드리면 다음과 같습니다.

클라이언트에서는 최종 변경된 아이템 ID 리스트만 넘어왔다고 가정했습니다. 

 

이에 따르면 ORDER_ITEM_ID PK 6, 7인 값은 FK인 ORDER_ID 4는 정상적으로 NULL로 업데이트를 했습니다.

이 과정에서 하이버네이트는 삭제가 아닌 참조를 지웠기 때문에 삭제가 아닌 null로 업데이트 하는 것이 맞는 판단이라고 정답을 내렸습니다.

delete문이 나가도록 하고 싶어서 옵션을 추가했습니다.

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

 

하지만 막힌 부분이 존재합니다.

초기 insert문에 order_id값이 존재하지않습니다! 그래서 찾아보니 createOrderItem() 메서드에서

새로운 객체를 생성했기 때문이라고 판단했습니다.

아 새롭게 추가되는 것은 비 영속상태였는데 이를 놓쳤습니다.

이를 통해 원하는 던 바를 이루었습니다.

 

여기서 제가 조언을 얻고 싶은 부분은 정말 이 과정이 정답인가에 대해서입니다.

  1. orderItems.setOrder(null) 말고 다른 방법은 없을까?

  2. 이는 OrderItems에 대한 변경인데 Order를 통해 처리하는 것이 맞는가?
    처음부터 OrderID를 통해 OrderItem들을 가져와 수정하는게 맞지 않을까?

  3. 내가 생각한 절차에서 문제가 될만한 부분은 없는 것인가?

등등.. 저에게 하나의 팁, 조언을 부탁 드리고 싶습니다.

 

긴 글 봐주셔서 감사합니다.

 

 

 

답변 0

답변을 작성해보세요.

답변을 기다리고 있는 질문이에요.
첫번째 답변을 남겨보세요!