본문 바로가기

JPA

[JPA] 영속성 전이 (CASCADE), 고아객체 제거 (ORPHAN)

영속성 전이 (CASCADE)

JPA는 CASCADE 옵션을 제공함으로써 부모 객체와 자식 객체의 영속성을 함께 관리할 수 있다. 즉 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장할 수 있다.

 

@Entity
@Getter
@Setter
@NoArgsConstructor
public class Parent {

    @Id @GaneratedValue
    @Column(name = "PARENT_ID")
    private Long id;
    
    @OneToMany(mappedBy = "parent")
    private List<Child> children = new ArrayList<>();

}
@Entity
@Getter
@Setter
@NoArgsConstructor
public class Child {

    @Id @GeneratedValue
    @Column(name = "CHILD_ID")
    private Long id;
    
    @ManyToOne
    @JoinColumn(name = "PARENT_ID")
    private Parent parent;

}

 

위와 같은 부모 클래스와 자식 클래스가 존재하고 서로 일대다 다대일 양방향 매핑이 되어있다고 했을때 만약 부모 1명에 자식 2명을 저장한다면 각각의 객체를 모두 em.persist() 메소드를 호출하여 저장해야 할 것이다.

=> JPA에서 엔티티를 저장할 때 연관된 모든 엔티티는 영속 상태여야 하기 때문!!

 

하지만 부모 클래스에서 연관관계를 설정하는 @OneToMany 어노테이션의 속성으로 cascade = CascadeType.PERSIST를 부여해주면 부모 객체만 em.persist() 메소드로 영속화 해줘도 자식 엔티티까지 함께 영속화돼서 저장된다.

 

public class Parent {

    // ...
    
    @OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)
    private List<Child> children = new ArrayList<>();

}

 

삭제할 때도 영속성전이가 가능하다. 삭제할 때는 cascade = CascadeType.REMOVE을 붙여주면 된다.

 

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

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

 

원래 부모와 자식 엔티티를 모두 삭제하려면 위와 같이 em.remove를 3번 호출해서 각각의 엔티티를 모두 삭제해줘야 하지만 cascade 속성을 REMOVE로 설정해주면 아래와 같이 부모 객체만 삭제해 줘도 연관된 자식 객체가 모두 함께 삭제된다.

 

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

 

참고로 삭제 순서는 항상 자식 부모 순이어야 한다. 그렇지 않으면 외래키 제약조건으로 인해 데이터베이스에서 외래키 무결성 예외가 발생한다.

고아 객체 (ORPHAN)

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

고아 객체 제거 기능을 사용하려면 부모 객체의 연관관계 엔티티에서 orphanRemoval 속성을 True로 설정해주면 된다.

 

public class Parent {

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

}

 

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

 

참고로 고아 객체 제거 기능은 참조가 제거된 엔티티는 다른 곳에서도 참조하지 않는 고아 객체로 보고 삭제하는 기능이다. 그렇기 때문에 참조하는 곳이 하나일 때만 사용가능하며 아래 두가지 경우에서만 사용할 수있다.

  • @OneToOne
  • @OneToMany

'JPA' 카테고리의 다른 글

[JPA] N + 1 문제와 해결방법  (0) 2022.10.19
[JPA] 객체지향 쿼리  (0) 2022.10.10
[JPA] 프록시, 즉시로딩, 지연로딩  (0) 2022.10.04
[JPA] 연관관계 매핑  (0) 2022.10.02
[JPA] 영속성 컨텍스트란(Persistence Context)?  (0) 2022.10.02