
제일 먼저 해야할 일은 Comment라는 엔티티를 정의해야 한다. 댓글과 다른 엔티티들과의 관계를 정의해보자.
따라서 아래와 같은 관계가 만들어진다.
@ManyToOne
private Question question;
@ManyToOne
private Answer answer;
@ManyToOne
private SiteUser author;
추가적으로 내용(content), 생성일(createDate), 수정일(modifyDate) 컬럼을 추가해줬다.
운영환경이라 생각했을 때 스프링 부트의 설정은 application-prod.properties > ddl.auto = none이다. 따라서 SQL 명령어로 Java로 작성한 Comment 엔티티를 테이블로 만들어보자.
CREATE TABLE `comment` (
`id` INT NOT NULL,
`content` TEXT NOT NULL,
`create_date` DATETIME NOT NULL,
`modify_date` DATETIME NULL,
`author_id` BIGINT NOT NULL,
`question_id` INT NOT NULL,
`answer_id` INT NOT NULL
);
ALTER TABLE `comment` ADD CONSTRAINT `PK_COMMENT` PRIMARY KEY (
`id`
);
ALTER TABLE `comment` ADD CONSTRAINT `FK_SITE_USER_TO_COMMENT_1` FOREIGN KEY (
`author_id`
)
REFERENCES `site_user` (
`id`
);
ALTER TABLE `comment` ADD CONSTRAINT `FK_QUESTION_TO_COMMENT_1` FOREIGN KEY (
`question_id`
)
REFERENCES `question` (
`id`
);
ALTER TABLE `comment` ADD CONSTRAINT `FK_ANSWER_TO_COMMENT_1` FOREIGN KEY (
`answer_id`
)
REFERENCES `answer` (
`id`
);
Comment 엔티티를 정의했으므로 엔티티를 만들고 수정하고 삭제하는 로직을 구현해보자. 로직 구현은 질문과 답변 엔티티에서도 했던 과정이므로 빠르게 진행했다.
(코드 생략)
단, 교재에 나와 있는 로직에서 예외처리 부분만 기존 로직과 규칙을 통일했다. 교재의 Comment 로직은 컨트롤러에서 Optional 예외처리를 진행한다. 기존 질문, 답변 로직은 서비스 계층에서 Optional 예외처리를 진행했기 때문에 서비스 계층에서 예외처리 하는 것으로 통일했다.
추가적으로 아래 블로그를 참고하여 스프링의 @ControllerAdvice 예외처리 방법을 적용했다.
스프링 예외처리 참고 자료
https://escapefromcoding.tistory.com/699 (여기 블로그 내용으로 적용)
https://mangkyu.tistory.com/204
https://mangkyu.tistory.com/205
질문, 답변, 댓글 엔티티를 조회 시 데이터가 없을 경우 발생하는 DataNotFoundException 을 GlobalBindingControllerAdvice에서 감지해서 @ResponseBody 형태의 예외를 브라우저에게 반환하게 됩니다. 반환 값은 ErrorResponse 클래스로 통일합니다.
@ControllerAdvice
public class GlobalBindingControllerAdvice {
@ExceptionHandler(DataNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
public ErrorResponse handleDataNotFoundException(Exception e) {
return ErrorResponse.of(e.getMessage(), HttpStatus.NOT_FOUND.value());
}
}
@Getter
@Builder
public class ErrorResponse {
private String message;
private int status;
public static ErrorResponse of(String message, int status) {
return ErrorResponse.builder()
.message(message)
.status(status)
.build();
}
}
새로 도입한 @ControllerAdvice에서 @ResponseStatus 값을 정의해주기 때문에 기존의 DataNotFoundException을 아래와 같이 수정합니다.
//@ResponseStatus 어노테이션 삭제
//@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "entity not found")
public class DataNotFoundException extends RuntimeException {
private static final long serialVersionUID = 1L;
public DataNotFoundException(String message) {
super(message);
}
}
SQL로 엔티티를 테이블로 생성하는 과정을 경험할 수 있었다.
ControllerAdvice를 이용함으로써 다음과 같은 이점을 누릴 수 있다.