JPA 영속성 전이 (CASCADE)
JPA 영속성 전이(CASCADE) 설정과 고아 객체 제거를 통해 부모 엔티티를 관리하는 방법을 설명합니다.
특정 Entity 를 영속 상태로 만들 때, 다른 엔티티도 영속 상태로 만들고 싶을 때 사용한다. CASCADE 를 사용하게 되면, 자식 Entity 는 부모 Entity 에 의해 관리할 수 있다. 하지만, DB 에서도 그렇듯 CASCADE 설정은 항상 종속관계가 포함될 때에만 사용되어야 한다.
1. Parent Class
package hellojpa.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import java.util.ArrayList;
import java.util.List;
@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);
    }
}
2. Child Class
package hellojpa.entity;
import javax.persistence.*;
@Entity
public class Child {
    @Id @GeneratedValue
    private Long id;
    private String name;
    @ManyToOne
    @JoinColumn(name = "PARENT_ID")
    private Parent parent;
}
3. Main Class 예제
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(); 를 매 번 호출해 주어야 한다.
            em.persist(parent);
            em.persist(child1);
            em.persist(child2);
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            if(em.isOpen()) {
                em.close();
            }
        }
        if(emf.isOpen()) {
            emf.close();
        }
    }
만약 Parent 에서 Child 까지 Persist 하려면, Parent.java 클래스에 Cascade 설정을 해 주면 된다. 그저 단순하게 반복을 돌면서 em.persist() 를 호출해 주는 것과 같은 효과를 지닌다.
package hellojpa.entity;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
public class Parent {
    @Id @GeneratedValue
    private Long id;
    private String name;
    // Cascade 타입을 설정한다.
    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
    private List<Child> childList = new ArrayList<>();
    public void addChild(Child child) {
        childList.add(child);
        child.setParent(this);
    }
}
CASCADE 의 종류
-CascadeType.ALL : 모두 적용
-CascadeType.PERSIST : 저장할 때에만 같이 관리하고 싶을 때
주의사항
만약 Child 가 Parent 외에 다른 요소들과도 사용될 때, CASCADE 로 절대 묶으면 안된다. 사용 예시 : 게시물과 첨부파일 관의 관계 와 같이 완전 종속의 관계일 때 사용하면 편하다.
고아 객체
-부모 Entity와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제한다.
-orphanRemoval = true 설정을 통해 제거한다.
Parent parent1 = em.find(Parent.class, id);
// 자식 엔티티를 컬랙션에서 제거
/*
DELETE FROM CHILD WHERE ID = ?
*/
parent1.getChildren().remove(0);
package hellojpa.entity;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@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);
    }
}
이것도 읽어보세요