부모 - 자식 엔티티 관계 삭제

2022. 4. 19. 18:10BackEnd(Java)/Spring Data JPA

부모 - 자식 관계를 가지는 엔티티 구조에서 통상적으로 부모가 삭제되면 자식도 같이 삭제가 되어야 한다.

(상황에 따라 자식 데이터가 필요할 경우 자식 데이터는 남겨 놓는다)

왜냐하면, 자식 입장에서 부모의 데이터가 존재해야 자식의 데이터가 유의미해진다.

 

부모 삭제 시 자식이 같이 삭제, 영속 등 기능을 JPA에서는 제공한다.

이러한 기능들 영속성 전이(CASCADE)라고 한다.

 

CASCADE에 대한 자세한 개념을 설명하지는 않을 것이다.

부모 -자식 관계의 삭제에 대해서 자세히 알아볼 것이다.

 

부모 - 자식 관계에서 자식 엔티티를 삭제하는 방법은 2가지가 있다.

 

1. 부모 삭제 시 자식도 같이 삭제하는 방법

 - CascadeType.REMOVE 혹은 orphanRemoval = true로 설정하여 부모를 삭제하면 자식도 함께 삭제된다.

 

2. 자식만 삭제하는 방법

- 부모 엔티티와 연관관계를 끊어 고아 객체를 만든 후 orphanRemoval = true 옵션을 줘서 고아 객체를 자동으로 삭제한다.

 

@OneToMany(mappedBy = "member", cascade = CascadeType.REMOVE, orphanRemoval = true)
private List<MemberImage> images =new ArrayList<>();

 //멤버 - 이미지 삭제(고아 객체 자동 삭제)
    public void deleteMamberImages(){
        int size=images.size();

        for(int i=0;i<size;i++)
            this.images.remove(0);
    }

 

위의 코드는 부모 삭제 시 자식도 같이 삭제되고 자식만 따로 삭제가 될 수 있게 진행하려고 한다.

 

그러나, cascade = CascadeType.REMOVE, orphanRemoval = true 옵션을 주고 deleteMemberImages() 함수를 호출해서 삭제를 해도 DELETE쿼리가 나가지 않는다.

 

삭제가 왜 안되는지에 대한 정확한 이유를 모른 채, cascade = CascadeType.ALL, orphanRemoval = true 옵션을 주고 테스트를 해보면 DELETE쿼리가 잘 작동하고 삭제가 된다.(?)

 

 

그런데, 내가 이해한 바로는 고아 객체 삭제는 orphanRemoval 옵션과 관련이 있지 cascade 옵션과는 관련이 없다고 이해했는데 구글링 해서 찾아봐도 내가 이해한 것과 같다.

JPA에서 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 고아 객체라고 한다. 고아 객체를 자동으로 삭제하는 기능을 제공하는 그 기능이 'orphanRemoval'이다. orphanRemoval=true 값을 주고 부모 엔티티의 자식 컬렉션에서 참조만 제거하면 자동으로 삭제된다라고 설명을 한다.

 

원일을 파악하지 못하는 와중에 나와 비슷한 상황을 글을 보게 되었다.

 

[HHH-9330] - Hibernate JIRA

회사에서 관리하는 프로젝트에 참여하고 있습니다

hibernate.atlassian.net

 

orphanRemoval 테스트 문제 · Issue #1 · jyami-kim/Jyami-Java-Lab

https://jyami.tistory.com/22 - 혼자 정리한 자료 : 제일 아랫단 링크 주소 [Parent.java] https://github.com/mjung1798/spring-boot/blob/master/jpa-lab/src/main/java/com/jyami/jpalab/domain/Parent.java [Child.java] htt...

github.com

 

위 링크를 타고 가면 orphanRemoval = true 옵션 값을 주고 양방향 관계에서 자식을 부모와 연관관계를 끊어도 실제 DELETE가 되지 않는 Hibernate 오류라고 한다.

 

따라서, 차선책은 자식을 직접 삭제하는 방법 혹은 cascade = CascadeType.PERSIST로 설정하여 삭제하라고 권유하고 있음....

 

일단 나는 persist 옵션을 줘서 삭제하기로 하였다. JPA를 쓰면서 복잡한 관계에서 삭제 행위는 진짜 머리 아프고 고려할 사항들이 많다고 느껴진다..

 

JPA 쓰기 너무 어렵다..😥😥

 

 

반응형