cascade = CascadeType.REMOVE와 @OnDelete(action = OnDeleteAction.CASCADE)의 차이

현주·2023년 5월 9일
0

✏️ 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번의 방법으로 조건을 충족시킬 수 있었다 !

💬 도움이 된 사이트

0개의 댓글