본문 바로가기
🌱BackEnd/JPA

[JPA] JPA에서 CascadeType.REMOVE, orphanRemoval=true

by Dong Ik 2023. 5. 1.

부모와 자식 관계의 엔티티(예를 들어 게시판과 댓글)를 설계 후 연관관계 매핑을 해주었다.

그 후 자식 엔티티의 일부를 제거하는 코드를 작성하는데 연관 관계는 제거되었지만 자식 엔티티의 데이터가 DB에 그대로 남아있었다. 관련된 문제를 해결하는 방법을 적어보았다.

 

 

1. JPA와 연관관계

JPA는 엔티티간의 연관관계를 쉽게 관리할 수 있다.

CascadeTypeorphanRemoval 옵션을 통해 부모 엔티티와 자식 엔티티의 관계를 효율적으로 관리할 수 있게 된다.

 

이 글에선 두 옵션의 기능과 발생하는 문제점에 대해서 적어보았다.

 

 

2. CascadeType.REMOVE

CascadeType.REMOVE는 부모 엔티티가 삭제될 때 연관된 자식 엔티티도 함께 삭제되는 옵션이다.

예를 들어, 부모 엔티티가 자식 엔티티와 일대다 관계를 가지고 있다면, 다음과 같이 CascadeType.REMOVE를 설정할 수 있다.

@Entity
public class Parent {
    @OneToMany(cascade = CascadeType.REMOVE)
    private List<Child> children;
}

하지만 다음과 같은 상황에 CascadeType.REMOVE 만으로는 부모 엔티티와의 관계가 끊어진 자식 엔티티(고아 객체)가 DB에 남게 될 수 있다.

 

 

컬렉션에서 자식 엔티티가 제거되는 경우

부모 엔티티가 자식 엔티티를 포함하는 컬렉션(현재 예시에서는 List)을 가지고 있는 경우, 이 컬렉션에서 특정한 자식 엔티티를 제거하면 부모 엔티티와 자식 엔티티간의 연관관계가 해제된다. CascadeType.REMOVE 옵션은, 부모 엔티티가 제거될 때 자식 엔티티를 제거하는 옵션이므로 이 상황에서는 자식 엔티티가 참조하는 부모 객체가 없는 고아상태가 된다.

parent.getChildren().remove(child);

 

고아 객체는 참조하는 부모 객체가 없는 상태다. 따라서 orphanRemoval 옵션을 이용해야 한다.

 

 

3. orphanRemoval=true

orphanRemoval=true는 부모 엔티티와 연관된 자식 엔티티 중에 관계가 끊어진 자식 엔티티를 자동으로 삭제하는 옵션이다.

(CascadeType.REMOVE는 부모 엔티티가 삭제되면 자식 엔티티를 삭제하는 옵션이므로 별개로 작동한다.)

다음과 같이 사용한다.

@Entity
public class Parent {
    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true)
    private List<Child> children;
}

 

만약 위의 경우처럼 

parent.getChildren().remove(child);

자식 엔티티의 컬렉션을 가져와 일부를 제거하는 경우, 참조하는 부모 객체가 없어진 고아 객체를 orphanRemoval=true 옵션을 통해 제거할 수 있다.

 

 

4. 결론

결론적으로, CascadeType.REMOVEorphanRemoval=true 옵션을 함께 사용하면 엔티티 간의 관계를 더욱 철저하게 관리할 수 있다.

이를 통해 애플리케이션의 데이터 일관성을 유지하고 실수로 인한 데이터 불일치를 방지할 수 있게 된다.