오늘은 삭제처리를 하면서 공부한 내용과 생각한 내용을 정리해보자!
현재 내가 구현하고자 하는 내용은 다음과 같다.
유저는 방을 참여할 수 있다. 또한 방에서 "퇴장"을 할 수 있다. 방에 존재하는 모든 유저가 "퇴장"시 해당 방은 없어져야 한다.
구현을 하면서 문제가 생겼다.
마지막 사람이 퇴장했을 경우, 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을 삭제할 경우 테이블의 외래키가 엮여있어서 삭제할 수 없는 것이다.
어떻게 해야할 지 천천히 생각해보자.
이 방법은 아무리 생각해도 별로다. 이유는
- Entity에 추가적인 연관관계가 생겨버리면 삭제처리하는 코드를 계속해서 추가해야 한다.
- "내가 참여했던 방"과 같은 추가적인 기능을 구현할 수가 없다.
어디선가 이것과 관련된 글을 본 적이 있다.
엔티티를 마음대로 삭제해버리면 그 엔티티와 DB에서 연관되어있는 내용뿐만 아니라 그 외적인 내용까지 문제가 생겨버리는 경우가 있다. 그래서 보통 구분자를 나두고 삭제하려는 테이블은 해당 구분자를 통해서 구분한다.
보통 JPA를 사용하는 프로젝트에서는 Cascade를 통해서 연관된 엔티티까지 일괄 삭제하는 방법을 이용한다.
이 방법이 현재 내 생각에서는 최선이다.
Enum의 내용은 다음과 같다.
- Deleted : 삭제 처리가 된 방(실제로는 삭제되지않고 식별자로 삭제 처리를 합니다.)
- Running : 삭제 처리가 되지 않은 방
기존 프로젝트에 추가적으로 구현한다. Status외의 추가적인 내용은 Git을 통해서 봐주세용
✅ Git 레포지토리
RoomStatus.java 생성
public enum RoomStatus {
//삭제 상태인 방
Deleted,
//진행 중인 방
Running;
}
@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);
끝!