1. 영속성 전이 : CASCADE
영속성 전이(CASCADE)는 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶을 때 사용하는 것이다.
ex) 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장
위의 그림을 코드로 만들고 실행시켜보겠다.
아래와 같이 Parent와 Child 엔티티를 만들고 연관관계를 맺어주었다.
@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);
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity
public class Child {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "parent_id")
private Parent parent;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
}
그리고 2개의 child를 생성하고 parent에 add 해주었다.
이 때, persist를 하면 총 3번을 호출해주어야 하는데 이 부분이 상당히 번거로운 작업이 된다.
번거롭다고 persist(child1), persist(child2) 이부분을 빼면 parent만 INSERT 쿼리가 날아가고, child 2개는 INSERT 되지 않는다.
public class CascadeMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
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);
tx.commit();
} catch (Exception e) {
tx.rollback();
e.printStackTrace();
} finally {
em.close();
}
emf.close();
}
}
parent를 주로 개발하고 싶고! 이렇게 번거롭게 persist를 하기 싫다! 이럴 때 사용하는 것이 바로 CASCADE이다.
바로 코드를 수정해보자! Parent 엔티티에 있는 childList에 cascade = CascadeType.ALL을 붙여주자
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
private List<Child> childList = new ArrayList<>();
그 후에 아래와 같이 main을 수정하고 실행시켜 보면
아래와 같이 INSERT 쿼리 3개를 날리는 것을 확인할 수 있고
DB에도 잘 들어가 있는 것을 확인할 수 있다.
CASCADE는 연관관계랑은 전혀 관계가 없고 persist를 할 때 cascade를 설정하면 연관된 엔티티도 같이 persist를 하겠다는 것이다.
CASCADE의 종류는 아래와 같다.
- ALL : 모두 적용
- PERSIST : 영속
- REMOVE : 삭제
- MERGE : 병합
- REFRESH
- DETACH
사용할 만한 종류는 ALL 또는 저장할 때만 생명주기를 같이 맞추고 나머지는 위험도가 있으니 따로 두겠다면 사용하는 PERSIST 정도가 있다.
정리
- CASCADE는 mappedBy, 연관관계 매핑과는 전혀 관계가 없다.
- A => B 관계가 cascade로 되어 있으면 A 엔티티를 persist할 때 B 엔티티도 연쇄해서 함께 persist 해버린다.
- 하나의 부모가 자식들을 관리할 때는 CASCADE를 사용할 수 있다. (생명주기가 동일할 때 사용)
- 게시판이나 첨부 파일 경로 같은 경우(한 게시물에서만 사용하는)에는 사용할 수 있다.
- 파일을 다른 경로나 다른 엔티티에서 관리하는 경우에는 사용하면 안된다.
- Child가 Parent가 아닌 다른 엔티티에서도 관리를 하거나 연관관계가 있는 경우에는 사용하면 안된다.
- 다른 엔티티가 Child를 알게 되는 것은 상관없다.
- 단일 엔티티에 종속적일 때 사용하는 것은 괜찮다.(단일 소유)
2. 고아 객체
부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제하는 것을 고아 객체 제거라고 한다.
설정하는 방법은 orphanRemoval = true 이렇게 설정을 해주면 된다.
아래와 같이 컬렉션에서 하나를 지우면 부모 엔티티와 연관관계가 끊어진 데이터를 삭제한다.
주의
- 참조가 제거된 엔티티는 다른 곳에서 참조하지 않는 고아 객체로 보고 삭제하는 기능이다.
- 참조하는 곳이 하나일 때 사용해야 한다.
- 특정 엔티티가 개인 소유할 때 사용해야 한다.
- @OneToOne, @OneToMany만 가능
- 참고 : 개념적으로 부모를 제거하면 자식은 고아가 된다. 따라서 고아 객체 제거 기능을 활성화하면, 부모를 제거할 때 자식도 함께 제거된다. 이것은 CasecadeType.REMOVE처럼 동작한다.
em.remove로 parent를 지워버리면 child도 같이 delete가 된다.
(CasecadeType.REMOVE로 설정을 하고 실행해도 동일한 결과가 나온다)
@OneToMany(mappedBy = "parent", orphanRemoval = true)
private List<Child> childList = new ArrayList<>();
또는
@OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE)
private List<Child> childList = new ArrayList<>();
3. 영속성 전이 + 고아 객체, 생명주기
스스로 생명주기를 관리하는 엔티티는 persist로 영속화, remove로 제거할 수 있다.
즉, 라이프사이클을 영속성 컨텍스트(엔티티 매니저)를 통해서 관리하는 것이다.
CascadeType.ALL과 orphanRemoval=ture 두 옵션을 모두 활성화하면 부모 엔티티를 통해서 자식의 생명주기를 관리할 수 있다.
도메인 주도 설계(DDD)의 Aggregate Root 개념을 구현할 때 유용하다.
'TIL > JPA' 카테고리의 다른 글
[TIL/JPA] 기본개념 : JPA의 다양한 쿼리 방법 소개 (0) | 2024.09.04 |
---|---|
[TIL/JPA] 기본개념 : 값 타입 (0) | 2024.08.31 |
[TIL/JPA] 기본개념 : 프록시와 연관관계 관리[즉시(EAGER)로딩, 지연(LAZY)로딩] (0) | 2024.08.27 |
[TIL/JPA] 기본개념 : 고급 매핑(상속관계 매핑, @MappedSuperclass) (0) | 2024.08.24 |
[TIL/JPA] 기본 개념 : 다양한 연관관계 매핑 (0) | 2024.08.22 |