override fun getTodoById(todoId: Long): TodoResponse {
// TODO: 만약 해당하는 할일 ID에 해당하는 할일이 없다면 throw ModelNotFoundExeption
// TODO: DB에서 카드 ID 기반으로 할일을 가져와서 CardResponse 감싸 변환 후 반환
val todo = todoRepository.findByIdOrNull(todoId) ?: throw ModelNotFoundException("Todo", todoId)
return todo.toResponse()
}
TodoServiceImpl.kt 파일은 이전 step과 바뀐 것이 없다. 그저 응답 DTO 클래스에서 할일 id값에 해당하는 댓글 리스트를 클라이언트에게 보낼 수 있게 CommentResponse DTO 클래스를 객체로 받는 리스트를 생성했다.
리스트를 생성한 이유는 map {} 으로 생성되는 것이 리스트이기 때문이다.
@Entity
@Table(name = "todo")
Class Todo(
...
@OneToMany(mappedBy="todo", fetch = FetchType.LAZY, cascade = [cascadeType.ALL], orphanRemoval = true)
var comments = MutableList<Comment> = mutableListOf()
...
) {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
fun addComment(comment: Comment) {
comments.add(comment)
}
fun removeComment(comment: Comment) {
comments.remove(comment)
}
...
}
fun Todo.toResponse(): TodoResponse {
return TodoResponse(
id = id!!,
userName = userName,
title = title,
plans = plans,
createdDate = createdDate,
doneStatus = doneStatus.name,
commentList = comments.map { it.toResponse() },
)
}
Todo.kt 파일에서 양방향 관계를 설정할 때 자식 테이블인 Comment 엔티티 클래스를 뮤터블 리스트로 생성한다.
이유는 Comment 데이터가 변할 수 있어 가변 리스트를 생성한 것이다.
또, 부모 엔티티 클래스인 Todo 안에 Comment 엔티티 클래스가 속해있기 때문이다. Todo에서 Comment 데이터를 찾을 수 있다.
아래의 Todo.toResponse()를 보면, Todo엔티티 클래스 객체를 이용해 TodoResponse를 반환받는 함수이다.
TodoResponse를 쓰면서 바로 return으로 TodoResponse를 반환받는다.
함수의 맨 아래 commentList = comments.map { it.toResponse() }
, TodoResponse DTO 클래스에서 만들었던 CommentResponse를 객체로 담은 리스트인 commentList에다가 위에서 자식 엔티티 클래스인 Comment를 데이터 더미로 모아놓은 뮤터블 리스트 comments를 map으로 쪼개 하나하나(it)를 즉, comment를 toResponse()하는 것이다. comment.toResponse()
data class TodoResponse (
...
var commentList = List<CommentResponse>
)
결국, 이 commentList에 들어가는 것은 comment.toResponse()
가 쌓인 리스트가 된다는 것이다.
- DB에 저장되는건 엔티티 클래스이다.
- Response는 클라이언트에게 응답으로 보내는 DTO 클래스이다.
- 비밀번호와 같은 개인정보를 반환하며 유출시키는 것을 방지한다.
- 엔티티 클래스가 변경돼도 Response에 지장이 가지 않는다.
- 내가 원하는 것만 뽑아 보낼 수 있다.