프로젝트 진행 중 스타일 delete를 테스트중에 외래키 제약 조건 위반 예외가 발생하였다.(java.sql.SQLIntegrityConstraintViolationException
)
해당 스타일이 댓글을 가지고 있으므로 가지고있는 댓글들에 있어서 처리할 방법을 몰라 예외가 발생했다고 생각하면 된다.
해결 방법은 여러가지 있겠지만 나는 스타일을 물리삭제 대신에 논리삭제를 하는 해결방법을 선택하였다.
이제 물리삭제와 논리삭제에 대해서 알아보자.
물리삭제는 SQL의 DELETE 명령어를 사용하여 직접 데이터를 삭제하는 방법이다.
아래와 같은 데이터가 있다고 가정해보자.
3번 데이터를 물리삭제 한다면 아래 사진처럼 될 것이다.
이처럼 삭제 대상의 데이터가 추후에 필요가 없을때 사용한다.
논리 삭제는 SQL의 UPDATE 명령어를 사용하여 삭제 여부를 알리는 컬럼에 값을 넣어 표시하는 방법이다.
위에서 봤던 데이터를 이번에는 논리삭제해보자.
UPDATE 명령어를 이용하여 삭제 여부의 컬럼을 True로 바꿔준다.
삭제를 했다지만 컬럼에 삭제 여부를 표시만한거와 마찬가지기에 데이터를 그대로 보관할 수 있다.
먼저 Style
테이블에 is_deleted
라는 컬럼을 추가하고 is_deleted
컬럼을 변경하는(삭제하는) deleteStyle
메서드를 생성한다.
※ 수정사항
@Entity
@Getter
@NoArgsConstructor
public class Style extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
@NotNull
private Member member;
@NotNull
private String styleImages;
@Enumerated(EnumType.STRING)
@Column(length = 20)
@NotNull
private Gender gender;
@NotNull
private Integer minHeight;
@NotNull
private Integer maxHeight;
@Column(length = 50)
@NotNull
private String styleCategory;
@NotNull
private String content;
@NotNull
private Integer viewCount;
@NotNull
private Long styleRank;
private LocalDateTime deleteDateTime;
public void deleteStyle(LocalDateTime deleteDateTime) {
this.deleteDateTime = deleteDateTime;
}
}
StyleService
서비스 코드에서 해당 컬럼을 변경해주는 로직을 작성한다.
@Transactional
public void delete(Long styleId) {
Style style = styleRepository.findById(styleId)
.orElseThrow(() -> new SmLogicException(ReturnCode.STYLE_NOT_FOUND));
style.deleteStyle(LocalDateTime.now());
}
StyleController
@DeleteMapping("/api/v1/styles/{styleId}")
public ApiResponse<?> delete(@PathVariable Long styleId) {
styleService.delete(styleId);
return ApiResponse.of(ReturnCode.SUCCESS);
}
postman으로 테스트시 삭제가 성공하는걸 확인할 수 있다.