Just Do IT!
JPA Cascade 알아보기 본문
Cascade란?
부모 엔티티가 영속화될 때 자식 엔티티도 같이 영속화되고, 부모 엔티티가 삭제될 때 자식 엔티티도 삭제되는 등 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 전이되는 것을 의미한다.
JPA에서는 영속성 전이를 Cascade 옵션을 통해 설정하고 관리할 수 있다.
JPA Cascade를 활용하면 ‘어떤 엔티티와 다른 엔티티가 밀접한 연관성이 있을 때’에 대한 관리가 매우 수월해진다.
예를 들어,
문제와 문제에 대한 댓글이 있다고 가정해보자.
문제와 댓글은 연관 관계에 있는 것이다. 이 두 연관 관계의 관리를 하는 데 cascade가 유용하게 사용된다.
Cascade 옵션
- ALL
- PERSIST
- MERGE
- REMOVE
- REFRESH
- DETACH
cascade는 여섯 가지 옵션이 있는데, 잘 사용되는 PERSIST, REMOVE, ALL에 대해서만 이야기하려고 한다.
CascadeType.PERSIST
부모와 자식 엔티티를 한 번에 영속화할 수 있는 옵션이다.
예를 들어 Board와 BoardComment가 있는 경우,
Board를 영속화한 경우 BoardComment까지 함께 영속화 되는 것이다.
CascadeType.REMOVE
PERSIST로 함께 저장했던 부모와 자식의 엔티티를 모두 제거할 경우에 사용하는 옵션이다.
원래는 board에 존재하는 댓글을 삭제해준 다음 부모 객체인 board를 삭제해야 한다.
그런데 이 옵션을 사용한 경우, 부모 객체를 삭제하면 연관된 자식 객체들이 전부 사라지는 것이다.
CascadeType.ALL
앞서 언급했던 PERSIST와 REMOVE 옵션을 모두 가지고 있는 옵션이다.
사실은 위 여섯 가지 옵션들이 모두 적용되는 옵션이다.
orphanRemoval = true와 CascadeType.REMOVE 비교하기
두 옵션은 아예 다른 사용법을 가지고 있다.
CascadeType.REMOVE 옵션은 논리적으로 참조를 변경시켜서 무결성 오류를 안 나게 할 뿐, 데이터는 그대로 존재하고 있다. 즉, 삭제가 되지 않는 것이다.
그래서 이럴 때 orphanRemoval=true 옵션을 사용해야 한다.
위에서 이야기했던 Board와 BoardComment 예시를 들어 다시 설명해본다면,
boardRepository.delete(id);
이런 식으로 board가 삭제된다면, boardcomment 객체는 부모 객체인 board와 연관 관계가 끊어지고 고아 객체가 된다.
고아 객체가 되었을 경우 해당 고아 객체를 자동으로 삭제해주는 옵션이 바로
orphanRemoval=true 인 것이다.
부모 엔티티를 삭제했을 경우는 CascadeType.REMOVE와 orphanRemoval=true 옵션이 동일하게 작동한다.
부모 엔티티를 삭제하면 자식 엔티티도 삭제된다.
그런데,
CasecadeType.REMOVE만 사용했을 경우 자식 객체가 그대로 남아있는 반면,
orphanRemoval=ture 옵션을 사용하는 경우 연관 관계가 끊어졌을 경우 자식 엔티티를 모두 제거해 준다.
CascadeType 옵션을 사용할 때 주의할 점
참조 무결성 제약조건 위반 가능성
CascadeType.REMOVE 또는 CascadeType.ALL 옵션을 사용하면 엔티티 삭제 시 연관 엔티티가 전부 삭제되기 때문에 의도하지 않게 참조 무결성 제약 조건을 위반할 수 있다.
참조 무결성 제약 조건
관계형 데이터베이스에서 릴레이션(relation)은 참조할 수 없는 외래 키를 가져서는 안된다는 조건
이를 위반하는 경우 데이터의 모순이 발생하게 된다.
양뱡향 연관관계 매핑 시 충돌 가능성
영속화에 대한 관리 지점이 두 곳인 경우 데이터 값을 예측할 수 없는 문제가 발생한다.
그래서 양방향으로 연관관계를 지정하는 경우 주의해야 한다.
프로젝트에서 관련 오류가 생겨서 팀원분이 해결해주셨다.
그걸 바탕으로 내가 맡은 문제집 쪽도 해결해야 했는데 코드를 보다가 의문이 생겨서 해결하고 겸사겸사 블로그에 기록하게 되었다.
참고 자료
https://tecoble.techcourse.co.kr/post/2023-08-14-JPA-Cascade/
https://resilient-923.tistory.com/417
'개발 공부 > Spring' 카테고리의 다른 글
[Spring] 스프링 부트에서 Redis 이용하기 (Window 11) (0) | 2024.11.09 |
---|---|
JPA 특정 엔티티 삭제 시 연관 관계 엔티티 삭제하기 (3) | 2024.10.29 |
[Spring Boot] 북마크 생성/삭제 토글 형식으로 구현하기 (0) | 2024.10.22 |
@RestControllerAdivce 적용해서 Spring 전역 예외처리하기 (1) | 2024.10.21 |
[Spring Boot] H2 Database를 사용하여 테스트 코드 작성하기 (1) | 2024.10.17 |