지난번에 했던 내용들에 이어서 개인과제를 도전해봤다.
- 2단계 : 댓글 CRUD
🔻 조건
- 일정에 댓글을 달 수 있습니다.
- 댓글과 일정은 연관관계를 가집니다.
- 댓글을 저장, 단건 조회, 전체 조회, 수정, 삭제할 수 있습니다.
- 댓글은 댓글 내용, 작성일, 수정일, 작성 유저명 필드를 갖고 있습니다.
일정과 연관관계를 가지려면 먼저 댓글에 관한 entity, dto, 3 Layer Architecture를 생성해야 한다.
또한 Todo 엔티티도 수정해야한다.
Todo 엔티티 수정하는데 1:N으로 연관관계 설정
@OneToMany(mappedBy = "todo")
private List<Comment> comments;
JPA에서 사용할 entitiy 객체 생성
@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "comment")
public class Comment extends Timestamped {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username", nullable = false)
private String username;
@Column(name = "content", nullable = false)
private String content;
@ManyToOne
@JoinColumn(name = "todo_id")
private Todo todo;
public void update(CommentRequestDto requestDto) {
this.username = requestDto.getUsername();
this.content = requestDto.getContent();
}
}
comment에서 사용할 dto(request, response)도 생성
package com.sparta.todo.dto;
import lombok.Getter;
@Getter
public class CommentRequestDto {
private String username;
private String content;
}
package com.sparta.todo.dto;
import com.sparta.todo.entity.Comment;
import com.sparta.todo.entity.Todo;
import lombok.Getter;
import java.time.LocalDateTime;
@Getter
public class CommentResponseDto {
private Long id;
private String username;
private String content;
private LocalDateTime createdAt;
private LocalDateTime modifiedAt;
private Long todoId;
public CommentResponseDto(Comment comment) {
this.id = comment.getId();
this.username = comment.getUsername();
this.content = comment.getContent();
this.createdAt = comment.getCreatedAt();
this.modifiedAt = comment.getModifiedAt();
this.todoId = comment.getTodo().getId();
}
}
이제는 Comment의 CRUD를 위해 세 가지 계층으로 나누어 개발할 3 Layer Architecture을 생성!
private final CommentService commentService;
public CommentController(CommentService commentService) {
this.commentService = commentService;
}
@PostMapping("/comment/{todoId}")
public ResponseEntity<CommentResponseDto> createComment(@PathVariable Long todoId, @RequestBody CommentRequestDto requestDto) {
return ResponseEntity.status(HttpStatus.CREATED).body(commentService.createComment(todoId, requestDto));
}
@GetMapping("/comment/{id}")
public ResponseEntity<CommentResponseDto> getComment(@PathVariable Long id) {
return ResponseEntity.status(HttpStatus.OK).body(commentService.getComment(id));
}
@GetMapping("/comment")
public ResponseEntity<List<CommentResponseDto>> getAllComments() {
return ResponseEntity.status(HttpStatus.OK).body(commentService.getAllComments());
}
@PutMapping("/comment/{id}")
public ResponseEntity<CommentResponseDto> updateComment(@PathVariable Long id, @RequestBody CommentRequestDto requestDto) {
return ResponseEntity.status(HttpStatus.OK).body(commentService.updateComment(id, requestDto));
}
@DeleteMapping("/comment/{id}")
public ResponseEntity<Void> deleteComment(@PathVariable Long id) {
commentService.deleteComment(id);
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}
private final CommentRepository commentRepository;
private final TodoRepository todoRepository;
@Transactional
public CommentResponseDto createComment(Long todoId, CommentRequestDto requestDto) {
// 해당하는 일정이 있는지 확인
Todo todo = findTodo(todoId);
// Comment Entity 생성
Comment comment = new Comment();
comment.setUsername(requestDto.getUsername());
comment.setContent(requestDto.getContent());
comment.setTodo(todo);
// DB에 저장
Comment newcomment = commentRepository.save(comment);
// Entity -> ResponseDto
CommentResponseDto commentResponseDto = new CommentResponseDto(newcomment);
return commentResponseDto;
}
public interface CommentRepository extends JpaRepository<Comment, Long> {
List<Comment> findAllByOrderByModifiedAtDesc();
}
또한 일정에서 댓글을 작성할 수 있어야 하므로 Todo의 Controller, Serivce에 추가
@PostMapping("/todo/comment/{id}")
public ResponseEntity<CommentResponseDto> createCommentToTodo(@PathVariable Long id, @RequestBody CommentRequestDto requestDto) {
return ResponseEntity.status(HttpStatus.CREATED).body(todoService.createCommentToTodo(id, requestDto));
}
@Transactional
public CommentResponseDto createCommentToTodo(Long id, CommentRequestDto requestDto) {
// Todo Entity가 있는지 확인
Todo todo = findTodo(id);
// Comment Entity 생성
Comment comment = new Comment();
comment.setUsername(requestDto.getUsername());
comment.setContent(requestDto.getContent());
comment.setTodo(todo);
// DB에 저장
Comment newcomment = commentRepository.save(comment);
CommentResponseDto commentResponseDto = new CommentResponseDto(newcomment);
return commentResponseDto;
}
Todo에서도, Comment에서도 댓글이 저장된다.