본 글은 인프런의 김영한님 강의 자바 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.ALL
CascadeType.PERSIST
CascadeType.REMOVE
CascadeType.DETACH
CascadeType.MERGE
CascadeType.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 = true
CascadeType.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
이 아닌 다른 타입과도 상황에 맞추어 적절히 활용될 수 있을 것이다.