JPA에서 @OneToMany 관계를 사용하다 보면 부모 엔티티에서 자식 엔티티를 제거했을 때 자식 데이터까지 함께 삭제하고 싶은 경우가 있다.
이때 사용할 수 있는 옵션이 orphanRemoval이다.
1. orphanRemoval이란?
orphanRemoval = true를 설정하면 부모 엔티티와의 연관관계가 끊어진 자식 엔티티를 DB에서도 삭제할 수 있다.
예를 들어 하나의 게시글(Post)에 여러 개의 댓글(PostComment)이 있다고 가정한다.
@Entity
public class Post extends BaseEntity {
@OneToMany(
mappedBy = "post",
cascade = {CascadeType.PERSIST, CascadeType.REMOVE},
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
}
게시글에서 특정 댓글을 제거한다.
public void removeComment(int commentId) {
comments.removeIf(comment -> comment.getId() == commentId);
}
이때 orphanRemoval = true가 설정되어 있다면 컬렉션에서 제거된 댓글은 고아 객체로 판단되어 DB에서도 삭제된다.
2. 왜 필요한가?
게시글과 댓글처럼 부모가 자식의 생명주기를 관리하는 관계에서 유용하다.
게시글에 속한 댓글을 단순히 List에서 제거하는 것만으로 끝내는 것이 아니라, 실제 데이터베이스에서도 해당 댓글을 삭제할 수 있기 때문이다.
public void removeComment(int commentId) {
comments.removeIf(comment -> comment.getId() == commentId);
}
따라서 서비스에서는 다음처럼 객체의 상태만 변경할 수 있다.
@Transactional
public void deleteComment(Post post, int commentId) {
post.removeComment(commentId);
}
트랜잭션이 종료될 때 JPA가 변경된 상태를 확인하고 필요한 DELETE SQL을 실행한다.
3. CascadeType.REMOVE와는 다르다
CascadeType.REMOVE와 orphanRemoval은 비슷해 보이지만 동작하는 상황이 다르다.
| 구분 | CascadeType.REMOVE | orphanRemoval |
| 기준 | 부모 엔티티 삭제 | 부모와 자식의 연관관계 제거 |
| 예시 | Post 삭제 → Comment 삭제 | Post에서 Comment 제거 → Comment 삭제 |
| 목적 | 삭제 작업 전파 | 고아 객체 삭제 |
questionRepository.delete(question);
처럼 부모 자체를 삭제할 때 자식도 삭제하도록 하는 것이 CascadeType.REMOVE이다.
post.getComments().remove(comment);
처럼 부모는 그대로 두고 자식과의 관계만 끊었을 때 자식까지 삭제하는 것이 orphanRemoval이다.
'BackEnd > Spring' 카테고리의 다른 글
| [Spring] REST API 순환참조 해결하기 - DTO와 Record 활용 (0) | 2026.08.12 |
|---|---|
| [Spring] Java Record란? DTO를 간결하게 만드는 방법 (0) | 2026.08.11 |
| [Spring] REST API란? SSR과 CSR 차이부터 JSON 응답까지 (0) | 2026.08.11 |
| [Spring] Validation 오류 처리하기 - BindingResult 활용 (0) | 2026.08.11 |
| [Spring] Validation으로 입력값 검증하기 (0) | 2026.08.11 |
댓글