내가 만들고 있는 프로젝트에서 Order
클래스와 Coupon
클래스는 1:1 연관 관계를 두고,
Order
클래스에 아래와 같이 Coupon
을 참조한 추가 데이터가 들어가 있는 구조였다.
위와 같이 한 후에 orderRepository.save()
를 하면 아래와 같은 에러가 발생했다.
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.assignment.productmanagementservice.domain.coupon.entity.Coupon; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.assignment.productmanagementservice.domain.coupon.entity.Coupon] with root cause
⠀
detached entity passed to persist: com.assignment.productmanagementservice.domain.coupon.entity.Coupon
detached entity passed to persist
관련 에러가 뜨는 경우는
이미 생성되어 있는 객체의 부분에 다시 한번 더 설정을 해주거나 저장을 해주려고 할 때 생기는 것이라고 한다.
( 즉, 엔티티 종속성 문제거나 객체 생성할 때 문제가 있는 것 )
일단 영속성 전이인 cascade 옵션을 찾아보니 아래와 같았다.
✔️ Cascade Type 종류
CascadeType.RESIST
➜ 엔티티를 생성하고, 연관 엔티티를 추가하였을 때persist()
를 수행하면 연관 엔티티도 함께persist()
가 수행됨
➜ 만약 연관 엔티티가 DB에 등록된 키값을 가지고 있다면detached entity passed to persist Exception
이 발생
⠀⠀CascadeType.MERGE
➜ 트랜잭션이 종료되고 detach 상태에서 연관 엔티티를 추가하거나 변경된 이후에 부모 엔티티가merge()
를 수행하게 되면 변경사항이 적용됨
( 연관 엔티티의 추가 및 수정 모두 반영됨 )
⠀⠀CascadeType.REMOVE
➜ 삭제 시 연관된 엔티티도 같이 삭제됨
⠀⠀CascadeType.DETACH
➜ 부모 엔티티가detach()
를 수행하게 되면, 연관된 엔티티도detach()
상태가 되어 변경사항이 반영되지 않음
⠀⠀CascadeType.ALL
➜ 모든 Cascade 적용
나의 경우 Cascade.ALL
옵션을 선택했는데
이후 save를 수행하면서 자식 객체인 Coupon
엔티티가 이미 DB 상에 존재하는데
Order
를 저장하면서 함께 중복 저장이 되어 에러가 발생한 것 같다.
이 경우에 간단한 해결 방법은 종속성 설정을 해제하고 각각을 따로 저장하는 것이라고 한다.
즉, 내가 설정했던 CascadeType.ALL
옵션을 제거하면 되는 것 !
그래서 나의 경우도 아래와 같이 제거하고 프로그램을 돌렸더니 잘 실행되었다 ㅎㅎ