
요구 사항
일정과 댓글의 연관 관계
지난 과제에서 만든 일정에 댓글을 추가할 수 있습니다.
ERD에도 댓글 모델을 추가합니다.
각 일정에 댓글을 작성할 수 있도록 관련 클래스를 추가하고 연관 관계를 설정합니다.
매핑 관계를 설정합니다. (1:1 or N:1 or N:M)
댓글 등록
-기능
선택한 일정이 있다면 댓글을 등록합니다.
-조건
댓글이 등록되었다면 client에게 반환합니다.
선택한 일정이 DB에 저장되어 있어야 합니다.
댓글을 식별하는 고유번호, 댓글 내용, 댓글을 작성한 사용자 아이디, 댓글이 작성된 일정 아이디, 작성일자를 저장할 수 있습니다.
⚠️ 예외 처리
선택한 일정의 ID를 입력 받지 않은 경우
댓글 내용이 비어 있는 경우
일정이 DB에 저장되지 않은 경우
댓글 수정
-기능
선택한 일정의 댓글을 수정합니다.
-조건
댓글이 수정되었다면 수정된 댓글을 반환합니다.
댓글 내용만 수정 가능합니다.
선택한 일정과 댓글이 DB에 저장되어 있어야 합니다.
⚠️ 예외 처리
선택한 일정이나 댓글의 ID를 입력 받지 않은 경우
일정이나 댓글이 DB에 저장되지 않은 경우
선택한 댓글의 사용자가 현재 사용자와 일치하지 않은 경우
댓글 삭제
-기능
선택한 일정의 댓글을 삭제합니다.
-조건
성공했다는 메시지와 상태 코드 반환하기
선택한 일정과 댓글이 DB에 저장되어 있어야 합니다.
⚠️ 예외 처리
선택한 일정이나 댓글의 ID를 입력받지 않은 경우
일정이나 댓글이 DB에 저장되지 않은 경우
선택한 댓글의 사용자가 현재 사용자와 일치하지 않은 경우
Entity
package com.sparta.homework2.entity;
import com.sparta.homework2.dto.CommentRequestDTO;
import jakarta.persistence.*;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotEmpty;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.time.LocalDateTime;
@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "comments")
public class Comment {
@Id
@GeneratedValue (strategy = GenerationType.IDENTITY)
private Long commentId;
@NotEmpty(message = "공백이거나 null인 것은 불가합니다.")
private String comment;
@Column(length = 100)
@Email
private Long userId;
private LocalDateTime createdAt;
@ManyToOne
@JoinColumn(name = "todo_id")
private Todo todo;
public Comment(Todo todo, CommentRequestDTO commentRequestDTO) {
this.comment = commentRequestDTO.getComment();
this.userId = commentRequestDTO.getUserId();
this.createdAt = LocalDateTime.now();
this.todo = todo;
}
public void updateComment(CommentRequestDTO requestDTO){
this.comment = requestDTO.getComment();
}
}
package com.sparta.homework2.controller;
import com.sparta.homework2.dto.CommentRequestDTO;
import com.sparta.homework2.dto.CommentResponseDTO;
import com.sparta.homework2.entity.Comment;
import com.sparta.homework2.service.CommentService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class CommentController {
private final CommentService commentService;
@PostMapping("/comment/{todoId}")
public CommentResponseDTO createComment(@PathVariable Long todoId, @RequestBody @Valid CommentRequestDTO requestDTO){
return commentService.createComment(todoId, requestDTO);
}
@PutMapping("/comment/{todoId}/{commentId}")
public CommentResponseDTO updateComment(@PathVariable Long todoId, @PathVariable Long commentId, @RequestBody CommentRequestDTO requestDTO){
return commentService.updateComment(todoId, commentId, requestDTO);
}
@DeleteMapping("/comment/{todoId}/{commentId}")
public ResponseEntity<String> deleteComment(@PathVariable Long todoId, @PathVariable Long commentId, @RequestHeader Long userId) {
commentService.deleteComment(todoId, commentId, userId);
return new ResponseEntity<>("댓글 삭제 성공했습니다.", HttpStatusCode.valueOf(201));
}
}
package com.sparta.homework2.service;
import com.sparta.homework2.dto.CommentRequestDTO;
import com.sparta.homework2.dto.CommentResponseDTO;
import com.sparta.homework2.entity.Comment;
import com.sparta.homework2.entity.Todo;
import com.sparta.homework2.repository.CommentRepository;
import com.sparta.homework2.repository.TodoRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Objects;
@Service
@RequiredArgsConstructor
public class CommentService {
private final CommentRepository commentRepository;
private final TodoRepository todoRepository;
public CommentResponseDTO createComment(Long todoId, CommentRequestDTO requestDTO) {
Todo todo = todoRepository.findById(todoId).orElseThrow(
() -> new IllegalArgumentException("선택한 일정이 없습니다.")
);
Comment comment = new Comment(todo, requestDTO);
commentRepository.save(comment);
return new CommentResponseDTO(comment);
}
@Transactional
public CommentResponseDTO updateComment(Long todoId, Long commentId, CommentRequestDTO requestDTO) {
todoRepository.findById(todoId).orElseThrow(
() -> new IllegalArgumentException("선택한 일정이 없습니다.")
);
Comment comment = commentRepository.findById(commentId).orElseThrow(
() -> new IllegalArgumentException("조회한 댓글이 없습니다.")
);
if (comment.getUserId().equals(requestDTO.getUserId())) {
comment.updateComment(requestDTO);
} else {
throw new IllegalArgumentException("사용자 ID가 일치하지 않습니다.");
}
return new CommentResponseDTO(comment);
}
public void deleteComment(Long todoId, Long commentId, Long userId) {
todoRepository.findById(todoId).orElseThrow(
() -> new IllegalArgumentException("선택한 일정이 없습니다.")
);
Comment comment = commentRepository.findById(commentId).orElseThrow(
() -> new IllegalArgumentException("조회한 댓글이 없습니다.")
);
if (comment.getUserId().equals(userId)) {
commentRepository.delete(comment);
} else {
throw new IllegalArgumentException("사용자 ID가 일치하지 않습니다.");
}
}
}
package com.sparta.homework2.repository;
import com.sparta.homework2.entity.Comment;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CommentRepository extends JpaRepository<Comment, Long> {
}
[Dto]
package com.sparta.homework2.dto;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
@Getter
@Setter
public class CommentRequestDTO {
private String comment;
private Long userId;
private Long todoId;
}
package com.sparta.homework2.dto;
import com.sparta.homework2.entity.Comment;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Getter
@NoArgsConstructor
public class CommentResponseDTO {
private Long userId;
private String comment;
private LocalDateTime createdAt;
public CommentResponseDTO(Comment comment) {
this.userId = comment.getUserId();
this.comment = comment.getComment();
this.createdAt = comment.getCreatedAt();
}
}
📝오늘의 회고
처음 이번 과제로 코드 짜면서 재미를 붙였다.