TroubleShooting
발생한 문제
프로젝트에서 Post를 삭제하려고 했으나 Post에 대한 좋아요를 했을 때 DB에 외래키가 저장되어 있어 삭제되지 않는 현상을 문제로 겪었다.
해결 및 시도 방법
1. 양방향 매핑 상태인가?
- 아니다. 단방향이며 영속성 전이에 대한 속성을 달아줄 수 없다. `cascade = CascadeType.ALL` 옵션을 달아 Cascade 되도록 처리할 수 있디만, 다음과 같은 조건을 만족해야 한다고 한다.
- 등록 삭제 등 라이프 사이클이 똑같을 때
- 단일 엔티티에 완전히 종속적일 때
2. 단방향 매핑을 유지하면서 할 수 있는 방법을 찾았다.
- `@OnDelete(action = OnDeleteAction.CASCADE)` 어노테이션을 달아주자.
- 하지만, 작동하지 않았다. 관련 정보를 더 공부했다.
- 알아보니 OnDelete에 대한 옵션은 JPA에서는 DB TABLE이 만들어지며 쿼리가 만들어 질 때만 설정이 가능한 것 같았다. 현재 프로젝트에서 ddl-auto의 설정값이 update이기 때문에 변경되지 않아 직접 SQL문을 통해 변경해주던지 Create 옵션을 사용해서 DB를 다시 생성하도록 해야 했다.

세부사항 변화
Cascade 문제가 두 번 겪게 되어 두 가지 방법을 모두 사용해 보았다.
1. Cascade 되길 원하는 필드에 OnDelete 어노테이션을 달고 `ddl-auto: create`로 바꾸어 주어 자동적으로 외래키 설정을 바꿔주도록 했다. 이 경우에는 만약 설정해둔 더미 데이터가 있다면 모두 데이터가 날라가는 방법이므로 데이터를 보존하고 싶다면 사용하면 안된다.

2. 두번째 방법은 직접 DB에서 SQL문을 통해 바꿔주었다. 하지만, 필자는 DBeaver 툴을 사용하기에 툴의 기능을 사용하였다 DBeaver는 자동으로 `ALTER TABLE ~~` SQL문을 만들어준다. 당연히 이 경우에도 `@OnDelete` 어노테이션을 달아야 한다.

수정
OnDelete 어노테이션을 설정!

다음과 같이 DBeaver를 통해 MySQL SQL문을 작성하여 Cascade 설정을 해주었다.
실제로 하게 되면 먼저 기존에 설정되어있던 외래 키를 삭제하고 다시 외래키를 만들 때 On Delete 설정을 해주어야만 한다.

실제 사용되는 SQL문은 다음과 같다.
1. 먼저 제약조건을 삭제한다.
alter table [테이블명] drop foreign key [제약조건명];
2. 이 후 제약조건을 설정한다.
alter table [추가할테이블명] add constraint [제약조건명] foreign key(컬럼명)
references [부모테이블명] (PK컬럼명) [ON DELETE CASCADE / ON UPDATE CASECADE];
결과
정상적으로 잘 작동하게 된다.
회고
이 과정을 통해 실제 SQL 에도 On Delete와 Update를 통해서 Cascade, Restrict 기능을 지원한다는 것을 알게 된 좋은 기회였던 것 같다. 또한 양방향, 단방향 매핑에서 고아객체를 삭제하는 다양한 방법들을 보고 이해하는 기회였다.
Cascade 자체가 JPA에서 제공하는 기능이라고 생각했던 것이 오산이었다. JPA 구현체인 하이버네이트에서 쉽게 사용할 수 있도록 어노테이션을 제공한다는 것을 알게 되었다.

.
'Troubleshooting' 카테고리의 다른 글
| TroubleShooting: warning: unknown enum constant When.MAYBE (0) | 2023.03.10 |
|---|---|
| Spring Security 필터로 인한 Swagger-ui.html 접속 불가 (0) | 2022.08.20 |
| Spring CORS 세팅 - addAllowedOriginPattern, isPreFlightRequest 관련 문제 (0) | 2022.08.17 |
| Controller - 같은 엔드포인트를 파라미터에 따라 나눠쓰기 (0) | 2022.08.15 |
| InvalidDefinitionException - jackson 직렬화 문제 + UserDto에 대한 고민 (0) | 2022.08.15 |