BackEnd/JPA

[JPA] 영속성 전이 - CASCADE & 고아 객체

JJangGu 2022. 6. 5. 00:37

이번에는 영속성 전이에 대해서 보겠습니다. 

cascade 라는 옵션으로 설정을 하게 될텐데, 먼저 "영속성 전이" 에 대한 개념부터 짚고 넘어가겠습니다.

 

영속성 전이라는 개념이 왜 필요한지에 대해서 이해를 하면 쉽습니다. JPA는 엔티티를 DB에 저장할 때 (flush) 영속성 컨텍스트에 엔티티가 올라가 있는 상태여야 된다는 것은 이제 알고있는 사실입니다. 그렇다면 부모 엔티티가 있고 자식 엔티티가 있다고 가정할 때, DB에 저장하고 싶으면 이들 모두가 영속 상태여야 하죠. 

 

이런 경우에 영속성이 전이가 된다면, 다르게 표현해서 부모를 영속 상태로 만들 때 자식까지 영속 상태로 만들 수 있다면 더 편하겠죠. 

 

@Entity
public class Parent {
    ...
    @OneToMany(mappedBy="parent", cascade=CascadeType.PERSIST)
    private List<Child> children = new ArrayList<>();
}

 

이렇게 옵션을 주었다고 하면, 부모 엔티티가 영속상태에 올라갈 때 자식도 같이 올라가게 됩니다. 이름 그대로 persist 되는 것이죠.

 

그런데 잠깐 고민해보면 영속 상태로 같이 올라가는건 알겠는데, 지워지는 경우도 있을 겁니다. 자동으로 영속화는 시켰는데, 지우는 것도 생각해야할 문제인거죠.

 

그럴때는 CascadeType.REMOVE 를 사용하면 됩니다.

 

CascadeType 에는 여러종류의 옵션이 있습니다. 

 

  • ALL : 모두 적용
  • PERSIST : 영속
  • MERGE : 병합
  • REMOVE : 삭제
  • REFRESH : Refresh
  • DETACH : Detach

이렇게 옵션들이 존재하고, cascade 옵션은 cascade = {CascadeType.PERSIST, CascadeType.REMOVE} 이렇게 어려 속성을 같이 사용할 수도 있습니다. 

 

여기서 PERSIST와 REMOVE 옵션은 em.persist() 나 em.remove() 가 실행될때 바로 전이가 일어나지 않고, flush 될 때 전이가 발생합니다. 

 

다음은 고아 객체에 대해서 알아보겠습니다.

 

부모 엔티티와 연관관계가 끊어진 자식 엔티티를 고아 객체라고 합니다. 그리고 JPA는 이것을 자동으로 삭제해주는 기능을 제공해줍니다.

 

@Entity
public class Parent {
	
    @Id @GeneratedValue
    private Long id;
    
    @OneToMany(mappedBy = "parent", orphanRemoval = true)
    private List<Child> children = new ArrayList<>();
    ...
}

 

이렇게 orphanRemoval 옵션을 통해서 설정할 수 있는 기능이고, 굉장히 편리해보입니다. 그런데 여기도 주의해야 할 점이 있습니다. 저 Child 엔티티를 하나의 Parent 가 소유해야 합니다. 

 

조금 생각해보면, 만약 여러개의 Parent 가 존재한다면 어느 한군데서 삭제되었다면 다른 참조에서 문제가 발생할 수 있습니다. 그런 이유로 orphanRemoval 은 @OneToOne 이나 @OneToMany 에서만 사용할 수 있습니다.

 

CascadeType.ALL, orphanRemoval = true 를 동시에 사용하면 생명주기를 관리하기 쉬워집니다. 

 

이렇게 되면 영속상태를 관리할때 persist(), remove() 를 통해서 추가, 제거되며 스스로 생명주기를 관리할 수 있고, 부모에서 제거될때 고아객체도 삭제되니 엔티티의 생명주기를 관리할 때 이점이 있습니다. 

 

영속성 전이에 대해서는 이렇게 마무리 해보겠습니다 👍