Application/JPA

[JPA] 영속성 전이 Cascade란?, 고아 객체 제거 OrphanRemoval란?

반응형
JPA에 대해서 헷갈렸던 개념들을 위주로 정리하는 글입니다.

자바 ORM 표준 JPA 프로그래밍

자바 ORM 표준 JPA 프로그래밍

특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶으면 JPA에서는 CASCADE 옵션으로 영속성 전이를 제공.

 

영속성 전이: 저장

CascasdeType.PERSIST

@Entity
public class Parent {
    ...
    @OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)
    private List<Child> children = new ArrayList<Child>();
    ...
}
private static void save(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(child2);

    em.persist(parent); // child도 영속성 전이로 저장
}

 

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


영속성 전이: 삭제

CascadeType.REMOVE

@Entity
public class Parent {
    ...
    @OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE)
    private List<Child> children = new ArrayList<Child>();
    ...
}
Parent findParent = em.find(Parent.class, 1L);
em.remove(findParent);

이 처럼 CascadeType.REMOVE로 설정하고 다음처럼 부모 엔티티만 삭제하면 연관된 자식 엔티티도 함께 삭제된다.


CASCADE의 종류

- ALL: 모두 적용

- PERSIST: 영속

- MERGE: 병합

- REMOVE: 삭제

- REFRESH: Refresh

- DETACH: DETACH


고아 객체 (Orphan), OraphanRemoval

JPA에서는 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제하는 기능을 제공하는데 이를 고아 객체 제거라 한다.

OrphanRemoval을 이용하면, 부모 엔티티의 컬렉션에서 자식 엔티티의 참조만 제거하면 자식 엔티티가 자동으로 삭제된다.

 

@Entity
public class Parent {

    @Id @GeneratedValue
    private Long id;

    @OneToMany(mappedBy = "parent", orphanRemoval = true)
    private List<Child> children = new ArrayList<Child>();
    ...
}
Parent parent = em.find(Parent.class, 10L);
parent.getChildren().remove(0); // 자식 엔티티를 컬렉션에서 제거 => 고아 객체가 되어 삭제

영속성 전이 + 고아 객체

일반적으로 엔티티는 EntityManager.persist()를 통해 영속화하고 remove()를 통해 제거되며 엔티티 스스로 생명주기를 관리한다.

하지만, CascadeType.ALL + orphanRemoval  = true를 동시에 사용하면 부모 엔티티를 통해서 자식의 생명 주기를 관리할 수 있다.

Parent parent = em.find(Parent.class, 10L);
parent.addChild(child); // 자식을 저장

Parent parent = em.find(Parent.class, 10);
parent.getChildren().remove(child); // 자식을 삭제
반응형