본문 바로가기
백엔드

[Spring Boot] JPA 영속성 전이, 고아 객체

by 육빔 2024. 9. 1.
728x90
반응형

영속성 전이(Cascade)란?

영속성 전이는 특정 엔티티의 상태가 변경될 때, 그와 연관된 다른 엔티티도 자동으로 동일한 상태 변화를 적용받도록 하는 것입니다. 이를 통해 코드의 간결성을 유지하고, 엔티티 간의 관계를 쉽게 관리할 수 있습니다. 말 그대로 종속, 파도처럼 같이 작용하는 것이라고 이해하면 편할 것 같습니다.

 

Cascade 유형

JPA에서 지원하는 CascadeType의 유형은 다음과 같습니다:

  1. CascadeType.PERSIST
    • 부모 엔티티가 저장(Persist)될 때, 연관된 자식 엔티티도 함께 저장됩니다.
    • 예를 들어, 부모 엔티티를 persist() 하면, CascadeType.PERSIST가 적용된 자식 엔티티도 자동으로 persist() 됩니다.
  2. CascadeType.MERGE
    • 부모 엔티티가 병합(Merge)될 때, 연관된 자식 엔티티도 함께 병합됩니다.
    • 부모 엔티티를 merge() 하면, CascadeType.MERGE가 적용된 자식 엔티티도 자동으로 병합됩니다.
  3. CascadeType.REMOVE
    • 부모 엔티티가 삭제(Remove)될 때, 연관된 자식 엔티티도 함께 삭제됩니다.
    • 부모 엔티티를 remove() 하면, CascadeType.REMOVE가 적용된 자식 엔티티도 자동으로 remove() 됩니다.
  4. CascadeType.REFRESH
    • 부모 엔티티가 새로 고침(Refresh)될 때, 연관된 자식 엔티티도 함께 새로 고침됩니다.
    • 부모 엔티티를 refresh() 하면, CascadeType.REFRESH가 적용된 자식 엔티티도 자동으로 refresh() 됩니다.
  5. CascadeType.DETACH
    • 부모 엔티티가 준영속(Detach) 상태로 전환될 때, 연관된 자식 엔티티도 함께 준영속 상태로 전환됩니다.
    • 부모 엔티티를 detach() 하면, CascadeType.DETACH가 적용된 자식 엔티티도 자동으로 detach() 됩니다.
  6. CascadeType.ALL
    • 모든 영속성 전이 옵션(PERSIST, MERGE, REMOVE, REFRESH, DETACH)을 한꺼번에 적용합니다.
    • 부모 엔티티에 대한 모든 작업이 연관된 자식 엔티티에도 동일하게 적용됩니다.

이렇게 있으나 보통 많이 쓰는 것은 ALL, REMOVE, PERSIST 정도를 가장 많이 사용합니다.

 

@Entity
public class Parent {
    
    @Id @GeneratedValue
    private Long id;

    private String name;

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

@Entity
public class Child {
    
    @Id @GeneratedValue
    private Long id;

    private String name;

    @ManyToOne
    @JoinColumn(name = "parent_id")
    private Parent parent;
    
}

 

고아 객체는 부모 엔티티와의 연관관계가 끊어져 더 이상 참조되지 않는 자식 엔티티를 의미합니다. JPA는 이런 고아 객체를 자동으로 삭제하는 기능을 제공하고, 데이터베이스의 무결성을 유지할 수 있도록 도와줍니다.

 

사용 가능한 연관관계

  • 고아 객체 제거 기능은 @OneToOne@OneToMany 연관관계에서만 사용 가능합니다. 이 기능을 활성화하려면 연관관계 설정 시 orphanRemoval = true를 지정합니다.

동작 방식

  • 고아 객체 제거 기능은 CascadeType.REMOVE와 유사하게 동작합니다. 부모 엔티티를 삭제하면, 부모와 연관된 자식 엔티티도 고아 객체로 간주되어 함께 삭제됩니다.
  • 부모 엔티티가 영속성 컨텍스트에서 제거되면(remove()), 부모 엔티티와 연관된 자식 엔티티도 자동으로 삭제되며, 이 과정에서 JPA는 고아 객체 제거를 처리하는 SQL 쿼리를 실행합니다.
@Entity
public class Parent {
    
    @Id @GeneratedValue
    private Long id;

    private String name;

    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Child> children = new ArrayList<>();
    
    public void addChild(Child child) {
        children.add(child);
        child.setParent(this);
    }

    public void removeChild(Child child) {
        children.remove(child);
        child.setParent(null);
    }
}

@Entity
public class Child {
    
    @Id @GeneratedValue
    private Long id;

    private String name;

    @ManyToOne
    @JoinColumn(name = "parent_id")
    private Parent parent;
    
    public void setParent(Parent parent) {
        this.parent = parent;
    }
}

 

사실 Cascade.ALL과 orphanRemoval = true의 차이를 잘 모르겠어서 더 찾아봤다.

 

 

  • CascadeType.ALL:
    • 부모 엔티티의 상태 변경 작업이 자식 엔티티로 전이됩니다. 즉, 부모 엔티티를 remove()하면 자식 엔티티도 함께 삭제됩니다. 하지만, 자식 엔티티가 부모 엔티티와의 연관관계에서 제거되었을 때 자식 엔티티를 삭제하는 기능은 없습니다.
  • orphanRemoval = true:
    • 자식 엔티티가 부모와의 연관관계에서 제거되면 자동으로 삭제됩니다. 이는 부모 엔티티의 삭제와는 별개로 자식 엔티티의 연관관계가 끊어졌을 때 자동으로 삭제되는 기능입니다.

 

 

한마디로 아래 경우일때 고아 객체 설정을 하면 용이하게 다룰 수 있다.

 

  • 부모 엔티티의 메서드를 통해 자식 엔티티를 명시적으로 제거하는 경우.
  • 부모 엔티티의 컬렉션에서 자식 엔티티를 직접 제거하는 경우.
  • 비즈니스 로직에 따라 자식 엔티티를 업데이트하거나 교체하는 경우.

 

 

728x90
반응형