본 글은 인프런의 김영한님 강의 자바 ORM 표준 JPA 프로그래밍 - 기본편 을 수강하며 기록한 필기 내용을 정리한 글입니다.
-> 인프런
-> 자바 ORM 표준 JPA 프로그래밍 - 기본편 강의
@OneToMany(GETTER, SETTER 생략)
< 글 (Post) >
addCommentAndSetPost(Comment comment)@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE")
private String title;
@Column(name = "CONTENT")
private String content;
@OneToMany(mappedBy = "post")
private List<Comment> comments = new ArrayList<>();
...
public void addCommentAndSetPost(Comment comment) {
this.comments.add(comment);
comment.setPost(this);
}
}
< 댓글 (Comment) >
@Entity
public class Comment {
@Id @GeneratedValue
@Column(name = "COMMENT_ID")
private Long id;
@Column(name = "CONTENT")
private String content;
@ManyToOne
@JoinColumn(name = "POST_ID")
private Post post;
}
// Post 생성 후 DB 저장
Post post1 = new Post();
post1.setTitle("Post Title");
post1.setContent("Post Content");
entityManager.persist(post1);
// Comment 생성 후 DB 저장
Comment comment1 = new Comment();
comment1.setContent("comment1");
post1.addCommentAndSetPost(comment1);
entityManager.persist(comment1);
// Comment 생성 후 DB 저장
Comment comment2 = new Comment();
comment2.setContent("comment2");
post1.addCommentAndSetPost(comment2);
entityManager.persist(comment2);
- 댓글은 글에만 달리고, 다른 곳에는 활용되지 않는다.
- 댓글이 유저 프로필에 달리거나, 주문 목록에 달리진 않을 것이다.
- 그렇다면 Comment는 온전히 Post만을 FK로 가리키고 있을 것이다.
- Post 외에는 연관관계를 맺는 엔티티가 없다.
영속성 전이와 고아 객체의 개념을 파악할 수 있다.< 영속성 전이 >
영속성 전이에 해당한다.< 고아 객체 >
고아 객체라 한다.cascade 속성을 활용해야 한다.< Post >
...
@OneToMany(mappedBy = "post", cascade = CascadeType.ALL)
private List<Comment> comments = new ArrayList<>();
...
Post post1 = new Post();
post1.setTitle("Post Title");
post1.setContent("Post Content");
Comment comment1 = new Comment();
comment1.setContent("comment1");
post1.addCommentAndSetPost(comment1);
Comment comment2 = new Comment();
comment2.setContent("comment2");
post1.addCommentAndSetPost(comment2);
entityManager.persist(post1);
CascadeType.ALLCascadeType.PERSISTCascadeType.REMOVECascadeType.DETACHCascadeType.MERGECascadeType.REFRESH고아 객체는 제거되어야 할 것이다.orphanRemoval = true@OneToMany(mappedBy = "post", orphanRemoval = true)
private List<Comment> comments = new ArrayList<>();
...
Post findPost = entityManager.find(Post.class, post1.getId());
entityManager.remove(findPost);
entityTransaction.commit();

@OneToOne, @OneToMany만 사용할 수 있다.CascadeType.REMOVE vs orphanRemoval = trueCascadeType.REMOVE와 orphanRemoval = true 모두 Post를 제거하면 Comment도 제거된다.<CascadeType.REMOVE>
- 상위 엔티티(Post)가 제거되면 하위 엔티티(Comment)도 제거된다.
- 상위 엔티티와 하위 엔티티의 참조가 끊어지는 경우에는 하위 엔티티가 제거되지 않는다.
- post1의 comments 필드에서 comment1을 제거하면 참조는 끊어지지만 comment1은 제거되지 않는다.
<orphanRemoval = true>
- 상위 엔티티가 제거되면 하위 엔티티도 제거된다.
- 상위 엔티티와 하위 엔티티의 참조가 끊어지는 경우, 하위 엔티티가 제거된다.
- post1의 comments 필드에서 comment1을 제거하면, comment1을 고아 객체로 분류하여 제거하는 것이다.
orphanRemoval = true는 기본적으로 고아 객체를 제거하는 기능임을 인지하면 될 것이다....
@OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Comment> comments = new ArrayList<>();
...
CascadeType.ALL + orphanRemoval = true로 함께 활용할 경우, 상위 엔티티를 통해 하위 엔티티의 생명 주기를 관리할 수 있게 된다.CascadeType.ALL이 아닌 다른 타입과도 상황에 맞추어 적절히 활용될 수 있을 것이다.