JPA Cascade란?

도리·2024년 10월 8일

JAVA

목록 보기
7/7

참고블로그

JPA Cascade란?

one to many, many to one 처럼 어떤 하나의 JPA 엔티티는 다른 엔티티와 연관 되어있는 경우가 있다.
대표적으론 게시글과 댓글이 있겟죠?
댓글 엔티티는 게시글 엔티티가 없다면 존재 의의가 없다.

게시판 어플리케이션을 만든다고 가정했을 때,
게시글을 삭제하는 서비스 로직은 어떻게 작성할 수 있을까?

@Transactional
public void deletePost(Long postId) {
    Post post = postRepository.findById(postId);
    List<Comment> comments = post.getComments();

    commentRepository.deleteAll(comments);
    postRepository.delete(post);
}

근데 여기서 몇가지 의문이 생긴다.

  • 게시물을 삭제할 때 댓글을 삭제하는 로직을 번거롭게 따로 또 작성해줘야하나?
  • 실수로 댓글 삭제 로직을 빼먹을 수도 있잖아...ㄷㄷ
  • 더 나은 방법 없나?

이런 문제점들의 해결책으로 JPA Cascade가 있다고 보면 되겠다.

JPA Cascade
A라는 엔티티에 어떤 작업을 수행할 때, 그 작업이 연관된 B라는 엔티티도 이루어져야 한다면 JPA Cascade를 유용하게 사용할 수 있는 것이다.

JPA Cascade Types

JPA에는 총 6개의 Cascade Type들을 지원하는데, 예제 코드와 함께 하나씩 살펴보겠다.

예제 코드에서 사용하는 엔티티는 앞서 말한 게시글(Post)와 댓글(Comment)이며, 실습 환경은 다음과 같다.
Post 엔티티의 물음표로 표시된 부분(Cascade Type)을 바꿔가면서 실습을 진행해보쟈!

  • Post 엔티티
@Entity
public class Post {

    @Id
    @GeneratedValue
    private Long id;

    private String title;

    @OneToMany(mappedBy = "post", cascade = ?)
    private List<Comment> comments = new ArrayList<>();

    // 생성자 생략

    public void addComment(Comment comment) {
        comments.add(comment);
    }
}
  • Comment 엔티티
@Entity
public class Comment {

    @Id
    @GeneratedValue
    private Long id;

    private String value;

    @ManyToOne
    @JoinColumn(name = "post_id")
    private Post post;
   
}

1. PERSIST

이는 엔티티를 영속화 할 때 연관된 엔티티도 함께 영속화 하는 타입이다

Post post = new Post();
Comment comment = new Comment();

post.addComment(comment);

entityManger.persist(post); // post, comment 둘 다 영속화

2. MERGE

엔티티 상태를 병합할 때 연관된 엔티티도 함께 병합하는 타입

Post post = new Post("this is post");
Comment comment = new Comment("this is comment");

post.addComment(comment);

entityManager.persist(post);
entityManager.persist(comment);

entityManager.flush();
entityManager.clear(); // 영속성 컨텍스트로부터 분리

post.setTitle("this is changed post");
comment.setValue("this is changed comment");

entityManager.merge(post); // post, comment 모두 변경사항 반영

REMOVE

엔티티를 제거할 때, 연관된 엔티티들도 함께 제거한다.

Post post = new Post();
Comment comment = new Comment();

post.addComment(comment);

entityManager.persist(post);
entityManager.persist(comment);

entityManager.remove(post); // post, comment 모두 삭제

REFRESH

엔티티를 새로고침할 때, 연관된 엔티티들도 함께 새로고침 한다.
여기서 새로고침이라는 의미는 데이터베이스로부터 실제 레코드의 값을 즉시 로징해서 덮어 씌운다는 것

Post post = new Post("this is post");
Comment comment = new Comment("this is comment");

post.addComment(comment);

entityManager.persist(post);
entityManager.persist(comment);

entityManager.flush(); // 데이터베이스에 반영

post.setTitle("this is changed post");
comment.setValue("this is changed comment");

entityManager.refresh(post); // 데이터베이스로부터 post, comment의 원본 값 즉시 로딩

System.out.println(post.getTitle()); // this is post
System.out.println(comment.getValue()); // this is comment

5.DETACH

엔티티를 영속성 컨텍스트로부터 분리하면 연관된 엔티티들도 분리된다.

Post post = new Post("this is post");
Comment comment = new Comment("this is comment");

post.addComment(comment);

entityManager.persist(post);
entityManager.persist(comment);

entityManager.detach(post); // post, comment 모두 영속성 컨텍스트로부터 분리됨

6. ALL

위에서 언급된 모든 타입들이 적용된다

profile
헬로

0개의 댓글