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);
    }


}

 


이것도 읽어보세요