본문 바로가기
JPA/JPA원리

20. 영속성 전이 : CASCADE, 고아객체

by 킹차니 2021. 7. 16.
김영한님의 인프런 강의와 PDF를 바탕으로 정리하였습니다.
https://www.inflearn.com/courses?s=%EA%B9%80%EC%98%81%ED%95%9C

 

영속성 전이 : CASCADE

 

영속성 전이란

특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶을 때

: 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장.

 

 

아래처럼 Parent와 Child 엔티티를 작성합니다. 

 

Parent

 

Child

맨 위의 표와 같이 Parent : Child 는 1:N 관계입니다.

 

아래 코드 처럼 child를 2개 작성하고 하나의 parent의 자식으로 만든 뒤, 생성한 3개의 객체(parent, child1, child2)를 persist하기 위해서는 총 3번의 persist가 필요합니다.

하지만 parent의 childList에 이미 2개의 child가 add된 상태인데 이렇게 3번의 persist를 할 필요가 있을까요?

하여 cascade를 사용할 수 있습니다.

 

아래는 cascade를 적용한 Parent엔티티입니다.

(cascade=All)추가

이래처럼 parent만 persist한 결과를 보시면 parent뿐 아니라 2개의 child까지 insert되었습니다.

parent의 persist만으로 child까지 insert

 

 

 

Cascade는 부모를 저장할 때 부모와 연관된 객체도 저장합니다.

 

 

영속성 전이: CASCADE - 주의!

1. 영속성 전이는 연관관계를 매핑하는 것과 아무 관련이 없습니다.

2. 엔티티를 영속화할 때 연관된 엔티티도 함께 영속화하는 편리함 을 제공할 뿐

 

 

CASCADE의 종류

ALL: 모두 적용

PERSIST: 영속

REMOVE: 삭제

MERGE: 병합

REFRESH: REFRESH DETACH: DETACH

 

 

Parent와 child만 연관관계가 있을 때는 써도 되지만 Child가 또 다른 엔티티와 연관관계가 있다면 Parent에 cascade는 쓰지  않는게 좋습니다.

 

 

 


 

 

고아객체

고아 객체 제거 : 부모 엔티티와 연관관계가 끊어진 자식 엔티티 를 자동으로 삭제합니다.

orphanRemoval = true

 

예를 들어 아래와 같은 코드가 있을 때

Parent parent1 = em.find(Parent.class, id);
parent1.getChildren().remove(0); //자식 엔티티를 컬렉션에서 제거

현재 parent의 childList에 있던 0번째 child는 고아 객체입니다.

이러한 고아객체를 자동으로 삭제하기 위해 orphanRemoval = true를 사용합니다.

 

 

Parent에 orphanRemoval = true를 적용하고 코드로 보겠습니다.

Parent엔티티

 

child1을 삭제하는 코드입니다.

아래 결과를 보시면 컬렉션에서 삭제했을 뿐인데, delete쿼리가 날라갔습니다. 

 

 

 

고아 객체 - 주의

  • 참조하는 곳이 하나일 때 사용해야함!
  • 참조가 제거된 엔티티는 다른 곳에서 참조하지 않는 고아 객체 보고 삭제하는 기능
  • 특정 엔티티가 개인 소유할 때 사용
  • @OneToOne, @OneToMany만 가능
  • 참고: 개념적으로 부모를 제거하면 자식은 고아가 됩니다. 따라서 고아 객체 제거 기능을 활성화 하면, 부모를 제거할 때 자식도 함께 제거됩니다. 이것은 CascadeType.REMOVE처럼 동작합니다.

 

 

 

영속성 전이 + 고아 객체, 생명주기 < CascadeType.ALL + orphanRemovel=true >

1. 스스로 생명주기를 관리하는 엔티티는 em.persist()로 영속화, em.remove()로 제거

 (아래 2번의 코드에서 Parent가 스스로 생명주기를 관리하는 엔티티입니다.)

 

2. 두 옵션을 모두 활성화 하면 부모 엔티티를 통해서 자식의 생명 주기를 관리할 수 있습니다.

즉 아래와 같습니다.

현재 persist도 parent만 했고, remove도 parent에 대해서만 했습니다만 child들도 따라서 persist되고, remove됩니다.

이것이 "부모 엔티티를 통해서 자식의 생명 주기를 관리"한다는 것입니다.

 

 

3. 도메인 주도 설계(DDD)Aggregate Root개념을 구현할 때 유용

'JPA > JPA원리' 카테고리의 다른 글

22. 값타입 - 기본값 타입, 임베디드 타입, 불변객체, 값타입 컬렉션  (0) 2021.07.17
21. 실전예제 적용해보기  (0) 2021.07.16
19. 지연로딩  (0) 2021.07.16
18. 프록시  (0) 2021.07.15
17. @MappedSuperclass  (0) 2021.07.14