- 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶을 때
ex) 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장
- @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
- 영속성 전이는 연관관계를 매핑하는 것과 아무 관련이 없음
- 엔티티를 영속화할 때 연관된 엔티티도 함께 영속화하는 편리함을 제공할 뿐임
ALL : 모두 적용 (라이프 사이클을 전부다 맞출 때)
PERSIST : 영속 (저장할때만 라이프 사이클을 맞출 때)
REMOVE : 삭제
MERGE : 병합
REFRESH : 새로고침
DETACH : 분리
하나의 부모가 자식들을 관리할때 사용해도됨
ex) 게시판, 첨부파일의 경로등
소유자가 하나일때는 사용이 가능하지만, 다른엔티티와 연관관계가 있을 경우 사용하면 안됨
cascade 적용 전
=====================================================================
Parent parent = new Parent();
Child child1 = new Child();
Child child2 = new Child();
parent.addChild(child1);
parent.addChild(child2);
entityManager.persist(parent);
entityManager.persist(child2);
entityManager.persist(child1);
=====================================================================
쿼리 실행
=====================================================================
/* insert org.hello.jpa.cascade.Parent
*/ insert
into
Parent
(name, id)
values
(?, ?)
Hibernate:
/* insert org.hello.jpa.cascade.Child
*/ insert
into
Child
(name, parent_id, id)
values
(?, ?, ?)
Hibernate:
/* insert org.hello.jpa.cascade.Child
*/ insert
into
Child
(name, parent_id, id)
values
(?, ?, ?)
=====================================================================
cascade 적용
=====================================================================
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
private List<Child> childList = new ArrayList<>();
=====================================================================
cascade 적용 후
=====================================================================
Parent parent = new Parent();
Child child1 = new Child();
Child child2 = new Child();
parent.addChild(child1);
parent.addChild(child2);
entityManager.persist(parent);
entityManager.persist(child2);
entityManager.persist(child1);
=====================================================================
쿼리 실행
=====================================================================
/* insert org.hello.jpa.cascade.Parent
*/ insert
into
Parent
(name, id)
values
(?, ?)
Hibernate:
/* insert org.hello.jpa.cascade.Child
*/ insert
into
Child
(name, parent_id, id)
values
(?, ?, ?)
Hibernate:
/* insert org.hello.jpa.cascade.Child
*/ insert
into
Child
(name, parent_id, id)
values
(?, ?, ?)
=====================================================================
컬렉션에서 제거된 객체를 DB 에서 DELETE
- 고아 객체 제거 : 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제
- orphanRemoval = true
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL , orphanRemoval = true)
=====================================================================
Parent parent = em.find(Parent.class , id);
parent.getChildList().remove(0) //자식 엔티티를 컬렉션에서 제거
//DELTE FROM CHILD WHERE ID = ?
=====================================================================
ex)
orphanRemoval = true 옵션 추가
=====================================================================
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL , orphanRemoval = true)
private List<Child> childList = new ArrayList<>();
=====================================================================
Parent의 childList에서 객체 제거
=====================================================================
findParent.getChildList().remove(0);
=====================================================================
쿼리 실행
=====================================================================
Hibernate:
/* delete org.hello.jpa.cascade.Child */ delete
from
Child
where
id=?
=====================================================================
- 참조가 제거된 엔티티는 다른곳에서 참조하지 않는 고아 객체로 보고 삭제하는 기능
- 참조하는 곳이 하나일 때 사용해야함
- 특정 엔티티가 개인 소유할 때 사용
- @OneToOne , @OneToMany 만 사용 가능
※ 참고
개념적으로 부모를 제거하면 자식은 고아가 된다.
따라서 고아 객체 제거 기능을 활성화 하면, 부모를 제거할 때 자식도 함께 제거된다.
이것은 CascadeType.REMOVE처럼 동작한다.
- cascade = CascadeType.ALL + orphanRemoval = true
- 스스로 생명주기를 관리하는 엔티티는 em.persist()로 영석화, em.remove()로 제거
- 두 옵션을 모두 활성화 하면 부모 엔티티를 통해서 자식의 생명 주기를 결정할수 있음
- 도메인 주도 설계(DDD)의 Aggregate Root 개념을 구현할 때 유용함