JPA Cascade

2020-09-14

영속성 전의란?

엔티티간 연관관계에 있는 경우, 즉 A엔티티와 B엔티티는 연관관계인 경우 A엔티티가 영속 상태일때 B엔티티도 영속 상태일까?
일반적으로 별도 설정을 해주지 않는다면 B엔티티는 영속상태가 아니다. 이 경우 B엔티티를 영속 상태를 만들기 위해 영속성 전이를 할 수 있다.
JPA는 CASCADE 옵션으로 영속성 전이 기능을 제공한다.

간단한 예제

만약 부모 1명에 자식 2명을 저장한다고 할때 영속성 전이를 이용하지 않는 다면 아래와 같이 작성하게 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static void saveNoCascade(EntityManager em) {
// 부모 저장
Parent parent = new Parent();
em.persist(parent);

// 1번 자식 저장
Child child1 = new Child();
child1.setParent(parent); // 자식 -> 부모 연관관계설정
parent.getChildren().add(child1); // 부모 -> 자식

// 2번 자식 저장
Child child2 = new Child();
child2.setParent(parent); // 자식 -> 부모 연관관계설정
parent.getChildren().add(child2); // 부모 -> 자식
em.persist(child);
}

영속성 전이 - 저장

영속성 전이를 활성화 하는 CASCADE옵션을 적용 해보자.

1
2
3
4
5
6
7
@Entity
public class Parent {
...
@OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)
private List<Child> children = new ArrayList<Child>();
...
}

CASCADE옵션을 지정 후 위의 저장 로직을 아래와 같이 수정 할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static void saveWithCascade(EntityManager em) {
Child child1 = new Child();
Child child2 = new Child();

Parent parent = new Parent();
child1.setParent(parent); // 연관관계 추가
child2.setParent(parent); // 연관관계 추가

parent.getChildren().add(child1);
parent.getChildren().add(child1);

// 부모 저장, 연관된 자식들 저장
em.persist(parent);
}

부모만 영속화 하면 CascadeType.PERSIST로 설정한 자식 엔티티까지 함께 영속화해서 저장한다.

CASCADE 종류

CascadeType 코드를 보면 아래와 같이 enum으로 정의되어있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public enum CascadeType { 
/** Cascade all operations - 모두 적용 */
ALL,
/** Cascade persist operation - 영속 */
PERSIST,
/** Cascade merge operation - 병합 */
MERGE,
/** Cascade remove operation - 삭제 */
REMOVE,
/** Cascade refresh operation */
REFRESH,
/**
* Cascade detach operation
*
* @since 2.0
*
*/
DETACH

참고로 CascadeType.PERSISTCascadeType.REMOVE 는 em.persist(), em.remove()를 실행할때 바로 전이가 발생하지 않고 플러시가 호출 될 때 전이가 발생한다.

고아 객체

JPA는 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제하는 기능을 제공하는데 이것ㄷ을 고아 객체(ORPHAN) 제거라 한다.
이 기능을 사용해서 부모 엔티티의 컬렉션에서 자식 엔티티의 참조만 제거하면 자식 엔티티가 자동으로 삭제되도록 설정 할 수 있다.
옵션중 orphanRemoval을 설정하면 고아 객체는 자동으로 삭제 된다.

1
2
3
4
5
6
7
8
9
@Entity
public class Parent {
@Id
@GeneratedValue
private Long id;

@OneToMany(mappedBy = "parent", orphanRemoval = true)
private List<Child> children = new ArrayList<Child>();
}