WindsomeProject - orphanRemoval 옵션 사용시 주의사항

박민수·2024년 3월 27일
0

WindsomeProject

목록 보기
16/32
post-thumbnail

개요

해당 포스팅에서는 상품 옵션 기능을 구현하고 기존의 상품 수정 메소드에 상품 옵션을 저장하는 과정에서 발생한 orphanRemoval 관련 문제를 해결한 과정에 대해서 정리해 보고자 한다.

발생한 오류

상품 옵션 기능을 구현하고 상품 수정 시 Product의 productOptions 필드에 상품의 옵션 값을 업데이트하는 과정에서 오류가 발생했다. 디버깅을 통해 확인해 본 결과 주어진 예외 메시지를 통해 orphanRemoval 관련된 문제임을 확인할 수 있었다.

예외 메시지는 다음과 같다.

org.springframework.orm.jpa.JpaSystemException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: com.windsome.entity.product.Product.productOptions; nested exception is org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: com.windsome.entity.product.Product.productOptions

오류가 발생한 코드는 다음과 같다.

Product Entity

public void updateProduct(ProductFormDTO productFormDto, Category category, List<ProductOption> productOptionList) {
    this.name = productFormDto.getName();
    this.price = productFormDto.getPrice();
    this.inventory = productFormDto.getInventory();
    this.productDetail = productFormDto.getProductDetail();
    this.productSellStatus = productFormDto.getProductSellStatus();
    this.discount = productFormDto.getDiscount();
    this.category = category;
    this.productOptions = productOptionList; // 이 부분에서 오류 발생
}

오류 원인

먼저 Product와 ProductOption은 1:N 연관 관계를 맺고 있으며, 연관 관계의 주인은 ProductOption이고, Product에서 ProductOption에 대한 orphanRemoval 속성을 true로 설정해 놓은 상태이다.

Product Entity

public class Product {
	...
    
	@OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<ProductOption> productOptions = new ArrayList<>();
    
    ...
}

ProductOption Entity

public class ProductOption {
	...
    
	@ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "product_id")
    private Product product;
    
    ...
}

해당 오류는 부모 엔티티의 컬렉션에서 orphanRemoval 속성이 설정된 상태에서 해당 컬렉션의 요소를 변경할 때 발생한다. 즉, 변경된 요소들이 더 이상 참조되지 않으면서 영속성 컨텍스트에서 관리되지 않게 되면 오류가 발생하는 것이다.

문제 해결

해당 오류를 해결하기 위해서는 기존 컬렉션의 요소를 삭제하고 새로운 요소를 추가하여 컬렉션을 업데이트해야 한다. 이를 위해 clear() 메소드를 사용하여 컬렉션을 비우고, addAll() 메소드를 활용하여 새로운 요소들을 추가했다.

Product Entity

public void updateProduct(ProductFormDTO productFormDto, Category category, List<ProductOption> productOptionList) {
    this.name = productFormDto.getName();
    this.price = productFormDto.getPrice();
    this.inventory = productFormDto.getInventory();
    this.productDetail = productFormDto.getProductDetail();
    this.productSellStatus = productFormDto.getProductSellStatus();
    this.discount = productFormDto.getDiscount();
    this.category = category;
    this.productOptions.clear(); // 추가한 코드
    this.productOptions.addAll(productOptionList); // 추가한 코드
}
profile
안녕하세요 백엔드 개발자입니다.

0개의 댓글

관련 채용 정보