해당 포스팅은 인프런에서 제공하는 김영한 님의 '자바 ORM 표준 JPA 프로그래밍 - 기본편'을 수강한 후 정리한 글입니다. 유료 강의를 정리한 내용이기에 제공되는 예제나 몇몇 내용들은 제외하였고, 정리한 내용을 바탕으로 글 작성자인 저의 언어로 다시 작성한 글이기에 서술이 부족하거나 잘못된 내용이 있을 수 있습니다. 그렇기에 해당 글은 개념에 대한 참고 정도만 해주시고, 강의를 통해 학습하시기를 추천합니다.
JPA에서 엔티티를 저장할 때 연관된 모든 엔티티가 영속 상태여야 한다. 이 때 영속성 전이(transitive persistence) 기능을 사용하며,CASCADE
옵션을 사용하면 부모 엔티티를 영속 상태로 만들 때 자식 엔티티를 함께 영속 상태로 만들 수 있다.
영속성 전이는 연관관계 매핑과는 아무 관련이 없으며, 엔티티를 영속화할 때 연관된 엔티티를 함께 영속화하는 기능만을 제공한다.
@Entity
public class Parent {
@Id @GeneratedValue
private Long id;
@OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)
private List<Child> children = new ArrayList<Child>();
}
@Entity
public class Child {
@Id @GeneratedValue
privaet Long id;
@ManyToOne
private Parent parent;
}
public 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);
}
위의 예제를 통해 알 수 있듯이 CascadeType.PERSIST
로 설정한 자식 엔티티는 부모 엔티티가 영속화할 때 함께 영속화되어 저장된다.
CascadeType.REMOVE
속성을 사용할 경우 엔티티를 삭제할 때도 영속성 전이를 사용할 수 있다. 삭제 순서는 외래 키 제약조건을 고려해서 자식을 먼저 삭제하고 부모를 삭제한다.
CascadeType
속성에는 다음과 같은 옵션이 있다.
ALL
: 모두 적용PERSIST
: 영속, flush 호출시 전이 발생MERGE
: 병합REMOVE
: 삭제, flush 호출시 전이 발생REFRESH
: REFRESHDETACH
: DETACHJPA의 고아 객체(ORPHAN) 제거는 부모 엔티티의 컬렉션에서 자식 엔티티의 참조만 제거하면 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제해주는 기능이며, 영속성 컨텍스트를 플러시할 때 적용된다. 이를 활성화하기 위해서는 자식 엔티티를 참조하는 컬렉션에 orphanRemoval = true
를 설정해주면 된다.
고아 객체 제거는 참조가 제거된 엔티티는 다른 곳에서 참조하지 않는 고아 객체로 보고 삭제하는 기능이기 때문에 참조하는 곳이 하나일 때만 사용해야 한다. 이런 이유로 orphanRemoval
은 @OneToOne
, @OneToOne
에서만 사용할 수 있다.
CascadeType.ALL
과 orphanRemoval = true
를 동시에 사용할 경우 부모 엔티티를 통해서 자식 엔티티의 등록/삭제 등 생명주기를 관리할 수 있다.