casecade=CascadeType.REMOVE
JPA 레벨에서 작동
JPA가 부모 엔티티를 삭제할 때 연관된 자식 데이터에 대한 DELETE 쿼리를 실행
외래 키를 찾아 참조하는 레코드를 제거하고, 참조하고 있는 레코드 수 만큼 DELETE 쿼리가 나감
부모 테이블의 자식 컬럼에 걸어여하므로(일반적으로 @OneToMany(cascade= CASCADE.REMOVE
) 양방향 매핑이 아닌 이상 적용하기 어려움
@OnDelete(action = OnDeleteAction.CASCADE)
DB에서 직접 처리
DDL 생성시 cascade 제약 조건이 생성됨
데이터베이스 자체에서 on delete cascade 제약조건이 걸리게 됨
➜ 삭제 쿼리가 나가지 않고 참조하는 레코드가 모두 제거됨
단방향 매핑에서도 적용이 가능
➜ 자식 테이블의 부모 컬럼에 적용하면 됨
✔️ DDL
- Data Definition Language로 데이터 베이스를 정의하는 언어
Ex. CREATE, ALTER, DROP, TRUNCATE 등
가장 큰 차이로는, JPA에 의해 처리되느냐 / DDL에 의해 DB 단에서 처리되느냐 이다.
정리하자면,
❗ casecade=CascadeType.REMOVE
는
JPA에 의해 외래 키를 찾아가며 참조하는 레코드를 제거해주는 기능으로
JPA 상에서는 참조하고 있는 레코드의 개수만큼 delete 쿼리가 생성된다.
⠀
❗ @OnDelete(action = OnDeleteAction.CASCADE)
는
DB 자체에서 on delete cascade 제약조건이 걸려 이를 통해 참조하는 레코드가 모두 제거되는 기능으로
JPA 상에서는 한 개의 delete 쿼리가 생성된다.
우리 프로젝트에서는 게시물인 Yata와 해당 게시물에 한 신청인 YataRequest 테이블이 1:N 관계였는데
아래와 같이 YataRequest 엔티티에는 Yata 엔티티가 @ManyToOne
으로 매핑되어있다.
여기서 아래 두 조건을 충족시켜야했다.
1. Yata(게시글)를 삭제할 경우,
해당 Yata와 연관된 YataRequest(신청)는 모두 삭제되어야 함
⠀
2. YataRequest(신청)를 삭제해도 신청한 Yata(게시글)는 삭제되면 안됨
이를 충족하기 위해 위의 두가지 방법을 시도해보았다.
1.
cascade = CascadeType.REMOVE
를 적용했을 때
➜ YataRequest 엔티티를 삭제하는 쿼리가 먼저 실행되고, 그 다음 Yata 엔티티를 삭제하는 쿼리가 실행된다.
⠀
그러나 YataRequest 엔티티 한 건을 삭제하려고 하면 Yata 테이블에 연관되어있는 데이터가 여러개 존재하므로 에러가 발생한다.
⠀
( Yata 엔티티와 연관된 YataRequest 엔티티가 한 건이면 에러 발생 X )
2.
@OnDelete(action = OnDeleteAction.CASCADE)
를 적용했을 때
➜ Yata를 삭제하면 YataRequest 까지 자동으로 삭제되고,
YataRequest 하나를 삭제해도 Yata가 자동 삭제 되지 않고 잘 남아있다.
그래서 나는 2번의 방법으로 조건을 충족시킬 수 있었다 !
💬 도움이 된 사이트