Cascade 개념
- 보통 엔티티 관계는 다른 엔티티의 존재에 의존한다.
- 대상 엔티티에 대해 일부 작업을 수행하면 연결된 엔티티에 동일한 작업이 적용된다.
- 즉 , 한쪽이 삭제가되면 해당 엔티티를 의존한 엔티티도 삭제가 되어야 한다.
JPA Cascade 유형
- all
- persist
- merge
- remove
- refresh
- detach
CascadeType.ALL
모든 작업을 부모 엔티티에서 자식 엔티티로 전파한다.
예제 코드
연관관계 설정은 아래와 같이 하였다.
Review
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "MEMBERS_ID")
@ToString.Exclude
private Member member;
Member
Member 엔티티의 pk 값을 Review 엔티티의 외래키로 참조하여 관계를 맺어 놓고 cascade 옵션을 CascadeType.ALL 로 설정한다.
외래키 값을 가지고 있는 Review 엔티티는 자식 엔티티에 해당하고 Member 엔티티는 부모 엔티티에 해당한다.
부모 엔티티 즉, Member 엔티티 정보를 삭제한다면 자식 엔티티도 삭제되는 행위가 전파된다.
테스트 코드
@Test
@DisplayName("Cascade ALL 테스트")
void cascade_ALL() {
// given
Member member = createMember("이기영", "기영@naver.com");
Review review = createReview("제목", "글내용");
review.addMember(member);
memberRepository.save(member);
reviewRepository.save(review);
// when
memberRepository.delete(member);
}
쿼리를 살펴보자
삭제 행위의 전파가 자식 엔티티에 잘 적용 된 것을 확인 할 수 있다.
저장 행위도 상위 항목만 저장하면 하위 항목도 같이 insert 되는 것을 볼 수 있다.
이렇듯 CascadeType.ALL 은 부모 엔티티의 모든 행위를 자식 엔티티에게 전파하겠다는 설정이라 생각하면 될 것이다.
CascadeType.PERSIST
상위 항목에서 하위 항목으로 지속 작업을 전파한다.
연관관계를 맺은 후 저장하는 행위를 생각해보자.
Member member = createMember("이기영", "기영@naver.com");
Review review = createReview("제목", "글내용");
review.addMember(member);
memberRepository.save(member);
reviewRepository.save(review);
위와 같은 코드로 연관관계 주인인 Review쪽에서 Member 를 저장하고 각 Repository에 저장 하는 것을 볼 수 있다.
하지만 아래와 같이 설정을 하면?
@Test
@DisplayName("Cascade PERSIST")
void cascade_PERSIST() {
Member member = createMember("이기영", "기영@naver.com");
Review review = createReview("제목", "글내용");
review.addMember(member);
memberRepository.save(member);
}
부모 엔티티의 행위를 자식 엔티티까지 전파하여 저장하는 행위를 부모 쪽에서 하면 자식 엔티티도 저장이 되는 것을 확인 할 수 있다.
CascadeType.MERGE
병합 작업의 행위를 부모 엔티티에서 자식 엔티티로 전파한다.
먼저 아래와 같이 cascade 설정을 한다.
다음으로 저장하고 수정하는 로직을 구현 해 본다.
@Test
@DisplayName("Cascade MERGE")
void cascade_MERGE() {
Member member = createMember("이기영", "기영@naver.com");
Review review = createReview("제목", "글내용");
review.addMember(member);
memberRepository.save(member);
reviewRepository.save(review);
Member findMember =
memberRepository.findById(member.getId()).orElseThrow();
findMember.setName("이기철");
memberRepository.save(findMember);
}
CascadeType.MERGE 설정으로 부모에서 자식까지 병합 작업을 전파하기 때문에 두 테이블 모두 update 할 것이다.
쿼리를 확인 해 보자.
두 테이블을 left join 하여 update 하는 쿼리를 확인 할 수 있다.
CascadeType.REMOVE
부모 엔티티를 삭제하면 자식 엔티티도 삭제 행위가 전파 된다.
CascadeType.DETACH
부모 엔티티를 영속성 컨텍스트에서 제거하면 자식 엔티티에게도 전파 된다.
CascadeType.REFRESH
데이터베이스에서 지정된 인스턴스의 값을 다시 읽는다.
CascadeType.LOCK
부모 엔티티를 영속성 컨텍스트 연결하면 자식 엔티티도 연결된다.
옵션이 더 있으므로 아래 참조에서 찾아보자.
참조:
https://www.baeldung.com/jpa-cascade-types
'JPA' 카테고리의 다른 글
[JPA] @OneToMany 단방향 매핑 이슈 (0) | 2022.12.08 |
---|---|
[Jpa] 테스트는 어느 부분까지 해야할까? (0) | 2022.08.26 |
[Jpa] 단일 테이블 전략의 상속 관계 매핑 이슈 (0) | 2022.08.20 |
[Jpa] 대댓글 계층구조 연관관계 메소드 이슈 (0) | 2022.08.12 |
[Jpa] Transaction Propagation (0) | 2022.08.06 |
[Jpa] Transaction Scope and Isolation (0) | 2022.08.05 |
[Jpa] Deprecated 된 getById() 대안 getReferenceById() (0) | 2022.08.02 |
[Jpa] Dirty Checking (0) | 2022.07.19 |