[픽플] JPA Repository deleteAll() 기능

이지우·2021년 5월 24일
0
post-thumbnail

픽플에는 [모집글] 혹은 [프로필]이 태그들을 가질 수 있다.
태그를 create할 때는 문제가 없었는데, 삭제를 하려니 FK가 걸려있어 삭제할 수 없다는 문제가 있었다.
처음에는 JPA Repository가 뭔가를 만들어두지 않았을까? 라는 생각을 초기에 못하고 하루종일 발품만 팔았다.

이슈 발생

픽플 엔티티 관계

픽플에서는 사용자 한 명이 하나의 프로필을 가질 수 있다.
사용자는 프로필을 생성할 때 태그 여러 개를 추가할 수 있다. 여기서 태그는 JAVA, C++같은 기술스택인데, 태그들을 나의 프로필에 추가함으로써
'나 이런 스킬 다룰 줄 알아요~' 를 알려줄 수 있다.
모집글도 마찬가지로 생성 시 태그 여러 개를 추가할 수 있다. 모집글에 태그를 추가하면 '이런 스킬을 다룰 줄 아는 사람을 모집해요~' 를 나타낼 수 있다.

따라서 위와 같은 관계가 설정된다.
하지만 다대다 관계이므로 프로필_태그 테이블, 모집글_태그 테이블을 별도로 생성해서 관리한다.

실제로는 아래와 같은 관계가 설정되어 있다.

태그 삭제

모집글과 프로필은 삭제 시 실제 DB에서 삭제되지 않고, 클라이언트 측에서 숨기므로 문제가 없다.
관리자는 태그를 추가하거나 삭제할 수 있는데, 추가 시에는 문제될 것이 없었다.
그러나 태그를 삭제하려고 하니, 프로필 or 모집글에서 가지고 있는 태그들이 있었기 때문에 Foreign key 문제가 발생해 삭제할 수 없었다.
JPA를 사용하기에, 삭제하기 위해 Cascade = CascadeType.ALL과 orphanRemoval = true 를 적용해놓고 나서 문제될 것 없겠지? 하며 안일하게 방치해두었던 것이 잘못이었다.
이후 문제가 터지고 알아보니 @OneToMany관계 즉, 태그 측이 연관관계의 주인이어야 태그를 삭제할 때 CASCADE 되어 삭제가 가능하다고 한다.
하지만 안타깝게도 관계를 매핑할 때 프로필_태그측에서 @ManyToOne을 걸어주었으므로 해당 Cascade를 사용할 수가 없었다. 힝

문제 해결

Jpa Repository , delete

JPA의 기능이 정말 놀라운 것 같다.
Jpa레포지토리에서 지원하는 delete를 사용해 해결했다.
기본적으로 CRUD 기능을 지원한다는 것을 알고는 있었는데, 눈앞에 주어진 것에만 급급해 기본을 놓친 것 같다.

우선 다대다 관계로 인해 새로 생긴 테이블들에 대한 Jpa Repository 인터페이스를 생성해줬다.

Profile_Tag JpaRepository

ProfileTagJpaRepository.java

RecruitmentBoard_Tag JpaRepository

RecruitmentBoardTagJpaRepository.java

위에서 공통적으로 들어간 저 한 줄의 deleteAllByTag_TagId(Long tagId); 를 SQL로 설명하자면,
delete from 테이블 where tagId = {tagId}; 와 같다.
tagId(삭제할 태그아이디)를 넣었을 때 일치하는 모든 컬럼들을 삭제하겠다는 의미이다.
이걸 왜 삭제하는가?

다시 엔티티를 보면

FK들이 잡혀있는 부분이 문제인 것이니, 해당 태그ID를 가진 모든 컬럼들을 삭제한 후 태그 자체를 삭제한다.

TagDeleteService.java


다만 Tag를 delete하는 api이니, TagDeleteService에서 두 개의 레포지토리를 호출해서, 연관된 모든 컬럼들을 삭제한 후 해당 태그를 삭제하는 것으로 마무리했다.

profile
개발 관찰일지

0개의 댓글