영속성 전이: CASCADE

2023. 7. 31. 15:02JPA

반응형

특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶으면 영속성 전이 기능을 사용하면 된다. JPA는 CASCADE 옵션으로 영속성 전이를 제공한다.

// 부모 엔티티
@Entity
public class Parent {

   @Id @GeneratedValue
   private Long id;
   
   @OneToMany(mappedBy = "parent")
   private List<Child> children = new ArrayList<Child>();
   ...
}

//자식 엔티티
@Entity
public class Child {
   
   @Id @GeneratedValue
   private Long id;
   
   @ManyToOne
   private Parent parent;
   ...
}

부모 엔티티가 여러가지 자식 엔티티를 가지고 있다.

// 부모 자식 저장
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); // 부모 -> 자식
   em.persist(child1);
   
   // 2번 자식 저장
   Child child2 = new Child();
   child2.setParent(parent); // 자식 -> 부모 연관관계 설정
   parent.getChildren().add(child2); // 부모 -> 자식
   em.persist(child2);
}

JPA에서 엔티티를 저장할 때 연관된 모든 엔티티는 영속 상태여야 한다. 따라서 예제를 보면 부모 엔티티도 영속 상태로 만들고 자식 엔티티도 각각 영속 상태로 만든다. 이럴 때 영속성 전이를 사용하면 부모만 영속 상태로 만들면 연관된 자식까지 한 번에 영속 상태로 만들 수 있다.

영속성 전이: 저장
@Entity
public class Parent {
   ...
   @OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)
   private List<Child> children = new ArrayList<Child>();
   ...
}

부모를 영속화할 때 연관된 자식들도 함께 영속화하라고 cascade = CascadeType.PERSIST 옵션을 설정했다. 

private static void saveWithCascade(EntityManager em) {
   
   Child child1 = new Child();
   Child child2 = new Child();
   
   Parent parent = new Parent();
   child1.setParent(parent); //연관관계 추가
   child2.setPatent(parent); //연관관계 추가
   parent.getChildren().add(child1);
   parent.getChildren().add(child2);
   
   //부모 저장, 연관된 자식들 저장
   em.persist(parent);
}

 

영속성 전이: 삭제

저장한 부모와 자식 엔티티를 모두 제거하려면 각각의 엔티티를 하나씩 제거해야 한다.

Parent findParent = em.find(Parent.class, 1L);
Child findChild1 = em.find(Children.class, 1L);
Child findChild2 = em.find(Children.class, 2L);

em.remove(findChild1);
em.remove(findChild2);
em.remove(findParent);

영속성 전이는 엔티티를 삭제할 때도 사용할 수 있다. CascadeType.REMOVE로 설정하고 다음 코드처럼 부모 엔티티만 삭제하면 연관된 자식 엔티티도 함께 삭제된다.

Parent findParent = em.find(Parent.class 1L);
em.remove(findParent);

만약  CascadeType.REMOVE를 설정하지 않고 위 코드를 실행하게 되면 부모 엔티티만 삭제된다. 하지만 데이터베이스의 부모 로우를 삭제하는 순간 자식 테이블에 걸려 있는 외래 키 제약조건으로 인해, 데이터베이스에서 외래키 무결성 예외가 발생한다.

CASCADE의 종류
public enum CascadeType {
   ALL,       // 모두 적용
   PERSIST,   // 영속
   MERGE,     // 병합
   REMOVE,    // 삭제
   REFRESH,   // REFRESH
   DETACH     // DETACH
}

다음처럼 여러 속성을 같이 사용할 수 있다.

cascade = {CascadeType.PERSIST, CascadeType.REMOVE}

위 코드는 em.persist(), em.remove()를 실행할 때 바로 전이가 발생하지 않고 플러시를 호출할 때 전이가 발생한다.

반응형

'JPA' 카테고리의 다른 글

객체지향 쿼리 언어 소개  (0) 2023.09.22
값 타입  (0) 2023.09.22
즉시 로딩과 지연 로딩  (0) 2023.07.31
프록시  (0) 2023.07.28
@SecondaryTable : 엔티티 하나에 여러 테이블 매핑  (0) 2023.06.13