쇼핑몰 프로젝트를 계속 진행하다 상품을 삭제하는 기능을 개발하게 되었다.
상품 엔티티를 삭제하게 되면, 연관되는 엔티티에도 영향을 끼치게 되어서 에러가 발생하였다.
또한 어떤 앤티티는 db에 유지하고 싶고, 어떤 엔티티는 db에서 삭제되기를 원하기도 하였다.
현재 연관관계 매핑은 이렇다.
멤버는 cart와 order와 likeItem 리스트를 가진다.
cart는 cartItem 리스트를 가진다.
cartItem은 item을 가진다.
order은 orderItem 리스트를 가진다.
orderItem은 item을 가진다.
likedItem은 item을 가진다.
item은 그 무엇도 가지지 않는다.
이 상황에서 Item을 삭제했을 때 내가 원하는 것은 다음과 같다.
1. Item을 삭제하면
2. cart의 cartItem db에 삭제되고, cart 리스트에서도 삭제되기를 원한다.
3. likedItem이 db에서 삭제되고, 멤버의 likeItem 리스트에서 삭제되기를 원한다.
4. orderItem은 db에서 삭제되지 않고, 멤버의 order 리스트에서도 삭제되지 않기를 원한다.
즉,
장바구니와 좋아요 상품은 리스트와 DB에서 모두 삭제되고,
주문 리스트와 주문 상품은 그대로 유지되기를 원한다.
따라서 2,3 을 해결하기 위해
allMembers.forEach(member -> {
//CartItem 제거 -> orphanRemoval 리스트에서 삭제되면 자동으로 db에 반영
member.getCart().getCarts().removeIf(cartItem -> cartItem.getItem().getId().equals(itemId));
//LikedItem 제거 -> orphanRemoval 리스트에서 삭제되면 자동으로 db에 반영
member.getLikedItems().removeIf(likedItem -> likedItem.getItem().getId().equals(itemId));
});
orphanRemoval을 통해 해결하였다.
cart와 order에서 각각의 상품들의 리스트에 orphanRemoval = true를 주게 되면,
각 리스트에서 상품들이 삭제되면, 자동으로 db에 반영된다. 즉, 리포지토리를 호출해서 delete를 손수 할 필요가
없다.
하지만 문제는 3번이었다.
3번은 Item이 삭제된 다음, 나중에 orderItem을 조회할 때, Item을 조회해야 하는데, 이때 이미 Item은 db에서
삭제되었기 때문에 오류가 발생헐 갓이다..
따라서 orderItem에 추가 정보 컬럼을 추가하고, Item을 삭제할 때, orderItem의 추가정보에 정보를 넣고,
item을 null로 해서 연관관계를 지우는 방식으로 수동으로 조작하기로 하였다.
최종코드
Item item = itemRepository.findById(itemId).orElseThrow(() -> new ItemHandler(ErrorStatus._ITEM_NOT_FOUND));
List<Member> allMembers = memberRepository.findAll();
allMembers.forEach(member -> {
//CartItem 제거 -> orphanRemoval 리스트에서 삭제되면 자동으로 db에 반영
member.getCart().getCarts().removeIf(cartItem -> cartItem.getItem().getId().equals(itemId));
//LikedItem 제거 -> orphanRemoval 리스트에서 삭제되면 자동으로 db에 반영
member.getLikedItems().removeIf(likedItem -> likedItem.getItem().getId().equals(itemId));
});
//orderItem 처리, 상품 삭제 이후, 조회 시 정보 집어넣기
List<OrderItem> allOrderItems = orderItemRepository.findAll();
allOrderItems.stream().filter(orderItem -> orderItem.getItem().getId().equals(itemId))
.forEach(orderItem -> orderItem.deleteOrders(item));
//아이템 삭제
itemRepository.deleteById(itemId);
return itemId;
'프로젝트' 카테고리의 다른 글
[트러블 슈팅] 스프링 시큐리티에서의 로그인 정보 dto 바인딩 오류 (0) | 2025.01.20 |
---|---|
[트러블 슈팅] cascade의 위험성.. (0) | 2025.01.11 |
[트러블 슈팅] git pull fatal: Could not read from remote repository. (0) | 2025.01.03 |
[트러블 슈팅] 상속관계에서의 builder 패턴 (1) | 2025.01.03 |
[트러블 슈팅] 일대일 관계에서 save 순서 및 외래키 관리 org.hibernate.TransientObjectException: persistent instance references an unsaved transient instance of (1) | 2025.01.02 |