JPA
[JPA] 영속성 전이(CASCADE)와 고아 객체 🐶
woochii
2023. 10. 21. 14:10
728x90
반응형
1. 영속성 전이(CASCADE)
- 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶을 때
- EX) 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장
CASCADE를 사용할 때
Parent
@Entity
public class Parent {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "parent")
private List<Child> childList = new ArrayList<>();
//연관관계 편의 메서드
public void addChild(Child child) {
childList.add(child);
child.setParent(this);
}
//Getter, Setter...
}
Child
@Entity
public class Child {
@Id @GeneratedValue
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "PARENT_ID")
private Parent parent;
//Getter, Setter...
}
JpaMain
Child child1 = new Child();
Child child2 = new Child();
Parent parent = new Parent();
parent.addChild(child1);
parent.addChild(child2);
em.persist(parent);
em.persist(child1);
em.persist(child2);
- 현재 Parent 중심으로 코드를 작성하고 있는데 em.persist()를 3번이나 호출하게 된다.
- em.persist(parent)만 하면 child도 한꺼번에 영속 상태로 만들고 싶다.
이때 Parent에서
@Entity
public class Parent {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL) //**
private List<Child> childList = new ArrayList<>();
//연관관계 편의 메서드
public void addChild(Child child) {
childList.add(child);
child.setParent(this);
}
//Getter, Setter...
}
JpaMain
Child child1 = new Child();
Child child2 = new Child();
Parent parent = new Parent();
parent.addChild(child1);
parent.addChild(child2);
em.persist(parent);
- Parent에서 Child와 매핑된 컬럼에서 cascade = CascadeType.ALL을 설정해주면
- em.persist(parent)만 해도 child도 같이 영속 상태가 된다.
영속성 전이의 목적
- 영속성 전이는 연관관계를 매핑하는 것과 아무 관련이 없다.
- 엔티티를 영속화할 때 연관된 엔티티도 함께 영속화하는 편리함을 제공할 뿐이다.
CASCADE의 종류
- ALL : 모두 적용
- PERSIST : 영속
- REMOVE : 삭제
- MERGE : 병합
- REFRESH : REFRESH
- DETACH : DETACH
영속성 전이를 사용할 수 없을 때
- Child같은 엔티티를 Parent가 아닌 또 다른 엔티티에서 관리한다면(연관관계가 있다면) 사용하면 안된다.
- 단일 엔티티에 완전히 종속적일 때 사용 가능하다.
2. 고아 객체
- 고아 객체 제거 : 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제해준다.
- orphanRemoval = true
Parent
@Entity
public class Parent {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true) //**
private List<Child> childList = new ArrayList<>();
//연관관계 편의 메서드
public void addChild(Child child) {
childList.add(child);
child.setParent(this);
}
//Getter, Setter...
}
JpaMain
Child child1 = new Child();
Child child2 = new Child();
Parent parent = new Parent();
parent.addChild(child1);
parent.addChild(child2);
em.persist(parent);
em.flush();
em.clear();
Parent findParent = em.find(Parent.class, parent.getId());
findParent.getChildList().remove(0);
실행 결과
Hibernate:
/* delete hellojpa.Child */ delete
from
Child
where
id=?
- findParent.getChildList().remove(0)으로 컬렉션에서 첫번째 Child를 삭제했더니
DELETE 쿼리가 실행되는 것을 볼 수 있다.
고아 객체 - 주의
- 참조가 제거된 엔티티는 다른 곳에서 참조하지 않는 고아 객체로 보고 삭제하는 기능
- 참조하는 곳이 하나일 때 사용해야함
- 특정 엔티티가 개인 소유할 때 사용
- @OneToOne, @OneToMany만 가능
- 참고
- 개념적으로 부모를 제거하면 자식은 고아가 된다.
- 따라서 고아 객체 제거 기능을 활성화하면, 부모를 제거할 때 자식도 함께 제거된다.
- 이것은 CascadeType.REMOVE처럼 동작한다.
3. 영속성 전이 + 고아 객체, 생명주기
- CascadeType.ALL + orphanRemoval = true
- 스스로 생명주기를 관리하는 엔티티는 em.persist()로 영속화, em.remove()로 제거
- 두 옵션을 모두 활성화하면 부모 엔티티를 통해서 자식의 생명주기를 관리할 수 있다.
- 도메인 주도 설계(DDD)의 Aggregate Root개념을 구현할 때 유용하다.
출처 : 자바 ORM 표준 JPA 프로그래밍 - 기본편
728x90
반응형