본문 바로가기

코딩 나도 할 수 있다!!

2024.05.27 (월) CRUD 만들기: Comment

기본적인 CRUD 구조는 다 만들었다
이제 댓글 기능을 추가해 볼 거다

 

package com.example.mytodo.comment.controller

import com.example.mytodo.comment.controller.dto.CommentResponse
import com.example.mytodo.comment.controller.dto.CreateCommentRequest
import com.example.mytodo.comment.controller.dto.UpdateCommentRequest
import com.example.mytodo.todoapp.service.TodoService
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*


@RequestMapping("/todo/{todoId}/comments")
@RestController
class CommentController(
    val todoService: TodoService
) {
    @GetMapping()
    fun getCommentList(
    ): ResponseEntity<List<CommentResponse>> {
        return ResponseEntity.ok(
            todoService.getCommentList()
        )
    }

    @GetMapping("/{commentId}")
    fun getComment(
        @PathVariable todoId: Long,
        @PathVariable commentId: Long
    ): ResponseEntity<CommentResponse> {
        return ResponseEntity.ok(
            todoService.getComment(todoId, commentId)
        )
    }

    @PostMapping()
    fun createComment(
        @PathVariable todoId: Long,
        @RequestBody createCommentRequest: CreateCommentRequest,
    ): ResponseEntity<CommentResponse> {
        val newComment: CommentResponse = todoService.createComment(todoId, createCommentRequest)
        return ResponseEntity.ok(newComment)
    }

    @PutMapping("/{commentId}")
    fun updateComment(
        @PathVariable todoId: Long,
        @PathVariable commentId: Long,
        @RequestBody updateCommentRequest: UpdateCommentRequest
    ): ResponseEntity<CommentResponse> {
        return ResponseEntity.ok(
            todoService.updateComment(todoId, commentId, updateCommentRequest)
        )
    }

    @DeleteMapping("/{commentId}")
    fun deleteComment(
        @PathVariable todoId: Long,
        @PathVariable commentId: Long
    ): ResponseEntity<Unit> {
        return ResponseEntity.ok(
            todoService.deleteComment(todoId, commentId)
        )
    }
}

기본적인 controller를 만들었다

앞선 CRUD를 만들었던 기능과 많이 다르지 않다

다른 부분이 있다면 val todoService: TodoService이다 

보통이면 commentService를 받을 건데 지금은 todo에 댓글을 달아야 하는 상황이기 때문에 TodoService를 받는다

 

그리고 Service부분은 

package com.example.mytodo.todoapp.service

import com.example.mytodo.comment.controller.dto.CommentResponse
import com.example.mytodo.comment.controller.dto.CreateCommentRequest
import com.example.mytodo.comment.controller.dto.UpdateCommentRequest
import com.example.mytodo.comment.model.Comment
import com.example.mytodo.comment.model.toCommentResponse
import com.example.mytodo.comment.repository.CommentRepository
import com.example.mytodo.todoapp.controller.dto.CreateTodoRequest
import com.example.mytodo.todoapp.controller.dto.TodoResponse
import com.example.mytodo.todoapp.controller.dto.UpdateTodoRequest
import com.example.mytodo.todoapp.model.Todo
import com.example.mytodo.todoapp.model.toTodoResponse
import com.example.mytodo.todoapp.repository.TodoRepository
import jakarta.transaction.Transactional
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service


@Service
class TodoService(
    val todoRepository: TodoRepository,
    val commentRepository: CommentRepository
) {
    fun getTodoList(): List<TodoResponse> {
        return todoRepository.findAll().map {
            it.toTodoResponse()
        }
    }

    fun getTodo(todoId: Long): TodoResponse {
        val result = todoRepository.findByIdOrNull(todoId)
        return result!!.toTodoResponse()
    }

    @Transactional
    fun createTodo(request: CreateTodoRequest): TodoResponse {
        return todoRepository.save(
            Todo(
                title = request.title,
                content = request.content,
                writer = request.writer
            )
        ).toTodoResponse()
    }

    @Transactional
    fun updateTodo(todoId: Long, request: UpdateTodoRequest): TodoResponse {
        val result = todoRepository.findByIdOrNull(todoId) ?: throw Exception("Todo")
        if (result == null) throw Exception("Todo not found")

        result.title = request.title
        result.content = request.content
        result.writer = request.writer
        return todoRepository.save(result).toTodoResponse()
    }

    @Transactional
    fun deleteTodo(todoId: Long) {
        val result = todoRepository.findByIdOrNull(todoId)

        todoRepository.delete(result!!)
    }

    fun getCommentList(): List<CommentResponse> {
        return commentRepository.findAll().map { it.toCommentResponse() }
    }

    fun getComment(todoId: Long, commentId: Long): CommentResponse {

        val comment = commentRepository.findByTodoIdAndId(todoId, commentId)
            ?: throw Exception("Comment not found")

        return comment.toCommentResponse()
    }

    @Transactional
    fun createComment(todoId: Long, request: CreateCommentRequest): CommentResponse {
        val todo = todoRepository.findByIdOrNull(todoId) ?: throw Exception("Todo not found")

        val comment = Comment(
            writerName = request.writerName,
            commentContent = request.commentContent,
            todo = todo
        )
        todo.createComment(comment)
        commentRepository.save(comment)
        return comment.toCommentResponse()
    }

    @Transactional
    fun updateComment(
        todoId: Long,
        commentId: Long,
        request: UpdateCommentRequest
    ): CommentResponse {
        val comments = commentRepository.findByTodoIdAndId(todoId, commentId)
            ?: throw Exception("Comment not found")

        val (writerName, commentContent) = request
        comments.writerName = writerName
        comments.commentContent = commentContent

        return commentRepository.save(comments).toCommentResponse()
    }

    @Transactional
    fun deleteComment(todoId: Long, commentId: Long) {
        val todo = todoRepository.findByIdOrNull(todoId)
            ?: throw Exception("Todo not found")
        val comment = commentRepository.findByIdOrNull(commentId)
            ?: throw Exception("Comment not found")
        commentRepository.deleteById(commentId)
    }
}

TodoService에 todoRepository와 CommentRepository를 연결한다

그다음 Entity 부분에 

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "todoId")
var todo: Todo
@OneToMany(mappedBy = "todo", cascade = [CascadeType.ALL], 
orphanRemoval = true, fetch = FetchType.LAZY)
var comments: MutableList<Comment> = mutableListOf()

이런 걸 쓰는데 이건 잘 모르겠다
나중에 찾아보거나 물어봐야겠다
이러면 대충은 다 완성했다
아직 모르는 부분이 많다
거의 외우다시피 적고 있는 터라 깊이감이 없다
외워서 적을 수 있다는 거도 다행이다
이 부분을 내 걸로 만들어 자연스럽게 나올 수 있도록 만들 것이다