[Spring Boot] 별도의 식별자로 삭제 처리하기

YoungHo-Cha·2022년 5월 28일
1

운동 매칭 시스템

목록 보기
16/17

오늘은 삭제처리를 하면서 공부한 내용과 생각한 내용을 정리해보자!


목차

  • 현재 이슈
  • 생각한 방향
  • 구현하기

현재 이슈

현재 내가 구현하고자 하는 내용은 다음과 같다.

유저는 방을 참여할 수 있다. 또한 방에서 "퇴장"을 할 수 있다. 방에 존재하는 모든 유저가 "퇴장"시 해당 방은 없어져야 한다.

구현을 하면서 문제가 생겼다.

마지막 사람이 퇴장했을 경우, JPA를 이용하여 다음 코드를 실행하였다.

roomRepository.deleteById(targetRoom.getId());

근데 다음과 같은 에러가 뜬다.

java.sql.SQLIntegrityConstraintViolationException: 
Cannot delete or update a parent row: a foreign key constraint fails 
..중략...

이유는 다음과 같다.

Room(1) : (N) Tag

구조라서 Room을 삭제할 경우 테이블의 외래키가 엮여있어서 삭제할 수 없는 것이다.

어떻게 해야할 지 천천히 생각해보자.


생각한 방향

모든 테이블에서 다 삭제처리하기

  1. Room과 외래키 연결이 되어있는 테이블의 레코드부터 순차적으로 삭제한다.
  2. 모든 외래키를 삭제했을 때, 해당 Room 레코드를 삭제한다.

이 방법은 아무리 생각해도 별로다. 이유는

  • Entity에 추가적인 연관관계가 생겨버리면 삭제처리하는 코드를 계속해서 추가해야 한다.
  • "내가 참여했던 방"과 같은 추가적인 기능을 구현할 수가 없다.

어디선가 이것과 관련된 글을 본 적이 있다.

엔티티를 마음대로 삭제해버리면 그 엔티티와 DB에서 연관되어있는 내용뿐만 아니라 그 외적인 내용까지 문제가 생겨버리는 경우가 있다. 그래서 보통 구분자를 나두고 삭제하려는 테이블은 해당 구분자를 통해서 구분한다.

보통 JPA를 사용하는 프로젝트에서는 Cascade를 통해서 연관된 엔티티까지 일괄 삭제하는 방법을 이용한다.

구분자 테이블 추가하기

이 방법이 현재 내 생각에서는 최선이다.

어떻게 해야하나?

  1. Room Entity에 Column을 추가한다.
  2. Column은 "Status"로 할 생각이다.
  3. java에서 Status는 Enum으로 구성된다.

Enum의 내용은 다음과 같다.

  • Deleted : 삭제 처리가 된 방(실제로는 삭제되지않고 식별자로 삭제 처리를 합니다.)
  • Running : 삭제 처리가 되지 않은 방

✅ 해당 내용 Git 이슈


구현하기

기존 프로젝트에 추가적으로 구현한다. Status외의 추가적인 내용은 Git을 통해서 봐주세용
✅ Git 레포지토리

Enum 만들기

RoomStatus.java 생성

public enum RoomStatus {
    //삭제 상태인 방
    Deleted,
    //진행 중인 방
    Running;
}

Column 추가하기 및 상태 변경 메소드 추가하기


@Getter
@Entity
@NoArgsConstructor
public class Room extends RoomBaseEntity {
	
    //... 중략 .../
    
    
    /*
    * 추가!
    */
    @Column(name = "ROOM_STATUS")
    @Enumerated(EnumType.STRING)
    private RoomStatus roomStatus;


    @Builder(access = AccessLevel.PRIVATE)
    private Room(RoomOfCreate roomOfCreate, User user){
        this.roomContent = roomOfCreate.getRoomContent();
        this.roomTitle = roomOfCreate.getRoomTitle();
        this.exercise = roomOfCreate.getExercise();
        this.endAppointmentDate = roomOfCreate.getEndAppointmentDate();
        this.startAppointmentDate = roomOfCreate.getStartAppointmentDate();
        this.limitPeopleCount = roomOfCreate.getLimitPeopleCount();
        this.host = user;
        this.participantCount = 1;
        this.createUser = user;
        this.roomArea = roomOfCreate.getRoomArea();
        this.viewCount = 0;
        this.createUser = user;
        
        
        //생성될 때 기본값 추가!
        this.roomStatus = RoomStatus.Running;

    }

    public static Room of(RoomOfCreate roomOfCreate, User user){

        return Room.builder()
                .roomOfCreate(roomOfCreate)
                .user(user)
                .build();
    }
	// 구분자 -> 삭제로 변경하는 메소드 추가!
	 public void setRoomStatus(RoomStatus roomStatus){
        this.roomStatus = roomStatus;
    }

    //... 중략 ...//

}

나가기 로직 수정하기

사실 나가기 로직을 제외하고도 수정할 부분이 상당히 많다. 조회 부분에 "Deleted"를 걸러서 조회되도록 한다던지..

일단 현재 문제가 생긴 "나가기" 부터 수정하자!

기존에 문제있던 코드

RoomRepository.deleteById(targetEntity.getId());

수정 코드

Room roomEntity = RoomRepository.findById(targetEntity.getId())
.orElseThrow(() -> new NotFoundRoomException("해당 방을 찾을 수 없습니다.");

//방 상태 변경
roomEntity.setRoomStatus(RoomStatus.DELETED);

끝!

profile
관심많은 영호입니다. 궁금한 거 있으시면 다음 익명 카톡으로 말씀해주시면 가능한 도와드리겠습니다! https://open.kakao.com/o/sE6T84kf

0개의 댓글