본문 바로가기

스프링 부트/JPA

[JPA] Cascade 간단 노트

2021-07-08글

JPA에서 엔티티를 저장할 때 연관된 모든 엔티티는 영속 상태여야 한다.
부모 엔티티를 영속 상태로 만들 때 연관된 자식도 한번에 영속 상태로 만들 수 있다.

Cascade란?

  • 영속성 전이
  • 연관관계에 있는 엔티티에 작업이 이루어져 상태 변화가 이뤄질 시 동일한 작업이 연결된 엔티티에 전이되는 옵션
  • 일반적으로 부모 엔티티에서 cascade 옵션을 걸어줌
  • 자식에서 부모로 옵션을 거는 것은 의미가 없다고함
  • 즉시로딩, 지연로딩, 연관관계 세팅과 관계 없음
  • 부모, 자식 엔티티와 연관관계 주인(외래키 관리자)는 다름

Entity의 상태

  • Transient : JPA가 모르는 상태 (단순 객체 생성)
  • Persistent : JPA가 관리중인 상태 (1차 캐시, Dirty Checking, Write Behind, ...)
  • Detached : JPA가 더이상 관리하지 않는 상태
  • Removed : JPA가 관리하긴 하지만 삭제하기로 한 상태

casecade 옵션 (일부)

PERSIST

  • 엔티티를 영속화 할 때 연관된 엔티티도 함께 유지
  • Transient 인스턴스를 Persistent로 만들어줌

REMOVE

  • 엔티티를 삭제할 때, 연관된 엔티도 함께 삭제

ALL

  • 모든 CASCADE 옵션 적용
  • 모든 작업을 부모에서 자식 엔티티로 전파

예시

아무런 옵션이 없는 경우

Comment

@Entity
public class Comment {

    @Id
    @GeneratedValue
    private Long id;
    private String comment;

    @ManyToOne
    private Post post;
} 

Post

@Entity
public class Post {

    @Id
    @GeneratedValue
    private Long id;
    private String title;

    @OneToMany(mappedBy = "post")
    private Set<Comment> comments = new HashSet<>();

    public void addComment(Comment comment) {
        this.getComments().add(comment);
        comment.setPost(this);
    }
}

Test 코드

  • 자식인 Comment는 저장되지 않음
    • id가 null임을 확인

CascadeType.ALL을 건 경우

  • 부모인 Post 엔티티에서 자식인 Comments에 옵션걸기

  • id가 null이 아님을 확인

고아 객체 제거

  • JPA에서는 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제하는 기능 제공
  • 참조가 제거된 엔티티는 다른 곳에서 참조하지 않는 고아 객체로 보고 삭제
  • 때문에 참조하는 객체가 하나일 때만 사용해야 함 (특정 엔티티에서만 소유하고 있는 엔티티)
  • @OneToOne, @OneToMany 에서만 사용 가능

Example

  • Comments 객체는 Post에서만 소유하고 있음
  • Comments에 orphanRemoval 옵션 추가

  • Comments를 제거하였을 때,

  • comment에 대해서 다음과 같이 delete 쿼리가 나감

참고 자료