@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long commentId;
@Column(nullable = false)
private String content;
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
@ManyToOne
@JoinColumn(name = "todo_id", nullable = false)
private Todo todo;
@Column(nullable = false, updatable = false)
private LocalDateTime createdAt; // 생성일
@PrePersist
protected void onCreate() {
this.createdAt = LocalDateTime.now();
}
// 생성자
@Builder
public Comment(String content, User user, Todo todo) {
this.content = content;
this.user = user;
this.todo = todo;
}
// 수정 메서드
public void update(String content) {
this.content = content;
}
}
댓글기능도 todo를 변형시켰듯이 밑에 Builder을 통해 생성과 수정을 담당하도록 바꾸고
public class CommentNotFoundException extends RuntimeException {
public CommentNotFoundException(String s) {
super("Comment not found");
}
}
이것과
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String s) {
super("User not found");
}
}
이걸 추가해준다.
@Service
public class CommentService {
private final CommentRepository commentRepository;
private final TodoRepository todoRepository;
private final UserRepository userRepository;
public CommentService(CommentRepository commentRepository, TodoRepository todoRepository, UserRepository userRepository) {
this.commentRepository = commentRepository;
this.todoRepository = todoRepository;
this.userRepository = userRepository;
}
public List<Comment> findAllComments() {
return commentRepository.findAll();
}
public Comment addComment(CommentRequestDto commentRequestDto, Long todoId, String userId) {
// 예외 처리
//예외 처리: 댓글 내용이 비어 있는 경우
if (commentRequestDto.getContent() == null || commentRequestDto.getContent().isEmpty()) {
throw new IllegalArgumentException("댓글 내용을 입력해 주세요.");
}
// 예외 처리: 선택한 일정의 ID를 입력받지 않은 경우
if (todoId == null) {
throw new IllegalArgumentException("일정 ID를 입력해 주세요.");
}
// 일정 확인, 예외 처리: 일정이 DB에 저장되지 않은 경우
Todo todo = todoRepository.findById(todoId)
.orElseThrow(() -> new IllegalArgumentException("일정이 존재하지 않습니다."));
// 사용자 확인, 예외 처리: 사용자가 DB에 저장되지 않은 경우
User user = userRepository.findById(Long.valueOf(userId))
.orElseThrow(() -> new IllegalArgumentException("사용자가 존재하지 않습니다."));
// 댓글 생성
Comment comment = new Comment();
comment.setContent(commentRequestDto.getContent());
comment.setTodo(todo);
comment.setUser(user);
return commentRepository.save(comment);
}
public Comment updateComment(Long commentId, CommentRequestDto commentRequest, Long todoId, String userId) {
// 예외 처리, 댓글이 비어있는 경우
Comment comment = commentRepository.findById(commentId)
.orElseThrow(() -> new IllegalArgumentException("댓글이 존재하지 않습니다."));
// 일정 확인. Todo 2에 만든 댓글을 todo1 이라고해도 수정되는거 막기
Todo todo = comment.getTodo();
if (!Objects.equals(todo.getId(), todoId)) {
throw new IllegalArgumentException("댓글이 해당 일정에 속하지 않습니다.");
}
// 사용자 확인
User user = userRepository.findById(Long.valueOf(userId))
.orElseThrow(() -> new IllegalArgumentException("사용자가 존재하지 않습니다."));
// 현재 사용자와 댓글 작성자 확인
if (!comment.getUser().getId().equals(Long.parseLong(userId))) {
throw new IllegalArgumentException("사용자가 일치하지 않습니다.");
}
// 댓글 내용 수정
if (commentRequest.getContent() != null && !commentRequest.getContent().isEmpty()) {
comment.setContent(commentRequest.getContent());
}
// comment.setTodo(todo);
// comment.setUser(user); 이것들 있으면 안됨 댓글 수정하면 2번일정에 있던 댓글이 1번으로 감
return commentRepository.save(comment);
}
public void deleteComment(Long commentId, String currentUserId) {
Comment comment = commentRepository.findById(commentId)
.orElseThrow(() -> new IllegalArgumentException("댓글이 존재하지 않습니다."));
// 현재 사용자와 댓글 작성자 확인
if (!comment.getUser().getId().equals(Long.parseLong(currentUserId))) {
throw new IllegalArgumentException("사용자가 일치하지 않습니다.");
}
commentRepository.delete(comment);
}
}
이것도
package com.teamsparta.task.comment.service;
import com.teamsparta.task.exception.TodoNotFoundException;
import com.teamsparta.task.comment.dto.CommentRequestDto;
import com.teamsparta.task.comment.model.Comment;
import com.teamsparta.task.comment.repository.CommentRepository;
import com.teamsparta.task.todo.model.Todo;
import com.teamsparta.task.todo.repository.TodoRepository;
import com.teamsparta.task.user.model.User;
import com.teamsparta.task.user.repository.UserRepository;
import com.teamsparta.task.exception.CommentNotFoundException;
import com.teamsparta.task.exception.UserNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@RequiredArgsConstructor
public class CommentService {
private final CommentRepository commentRepository;
private final TodoRepository todoRepository;
private final UserRepository userRepository;
// 모든 댓글 조회
public List<Comment> findAllComments() {
return commentRepository.findAll();
}
// 새로운 댓글 추가
public Comment addComment(CommentRequestDto commentRequestDto, Long todoId, String userId) {
validateCommentRequest(commentRequestDto, todoId);
Todo todo = findTodoById(todoId);
User user = findUserById(userId);
Comment comment = Comment.builder()
.content(commentRequestDto.getContent())
.todo(todo)
.user(user)
.build();
return commentRepository.save(comment);
}
// 댓글 업데이트
public Comment updateComment(Long commentId, CommentRequestDto commentRequest, Long todoId, String userId) {
Comment comment = findCommentById(commentId);
validateTodoOwnership(comment, todoId);
validateUserOwnership(comment, userId);
// update 메서드를 사용하여 댓글 내용 수정
comment.update(commentRequest.getContent());
return commentRepository.save(comment);
}
// 댓글 삭제
public void deleteComment(Long commentId, String userId) {
Comment comment = findCommentById(commentId);
validateUserOwnership(comment, userId);
commentRepository.delete(comment);
}
// 유효성 검증 메서드
private void validateCommentRequest(CommentRequestDto commentRequestDto, Long todoId) {
if (commentRequestDto.getContent() == null || commentRequestDto.getContent().isEmpty()) {
throw new IllegalArgumentException("댓글 내용을 입력해 주세요.");
}
if (todoId == null) {
throw new IllegalArgumentException("일정 ID를 입력해 주세요.");
}
}
// 일정 조회
private Todo findTodoById(Long todoId) {
return todoRepository.findById(todoId)
.orElseThrow(TodoNotFoundException::new);
}
// 사용자 조회
private User findUserById(String userId) {
return userRepository.findById(Long.valueOf(userId))
.orElseThrow(UserNotFoundException::new);
}
// 댓글 조회
private Comment findCommentById(Long commentId) {
return commentRepository.findById(commentId)
.orElseThrow(CommentNotFoundException::new);
}
// 일정 소유권 검증
private void validateTodoOwnership(Comment comment, Long todoId) {
if (!comment.getTodo().getId().equals(todoId)) {
throw new IllegalArgumentException("댓글이 해당 일정에 속하지 않습니다.");
}
}
// 사용자 소유권 검증
private void validateUserOwnership(Comment comment, String userId) {
if (!comment.getUser().getId().equals(Long.valueOf(userId))) {
throw new IllegalArgumentException("사용자가 일치하지 않습니다.");
}
}
}
이렇게 바꿔서 comment 엔티티의
@Builder
public Comment(String content, User user, Todo todo) {
this.content = content;
this.user = user;
this.todo = todo;
}
// 수정 메서드
public void update(String content) {
this.content = content;
}
과 연결하고, 구외에도 추가한 예외들과 연결한다.
컨트롤러도
@RestController
@RequestMapping("/api/comments")
@RequiredArgsConstructor
public class CommentController {
private final CommentService commentService;
@Operation(summary = "모든 댓글 조회")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Fetched all comments.")
})
@GetMapping
public ResponseEntity<List<CommentResponseDto>> getComments() {
List<Comment> comments = commentService.findAllComments();
List<CommentResponseDto> responseDtos = comments.stream()
.map(comment -> new CommentResponseDto(
comment.getCommentId(),
comment.getContent(),
comment.getUser().getId().toString(),
comment.getCreatedAt().toString()
))
.collect(Collectors.toList());
return ResponseEntity.ok(responseDtos);
}
@Operation(summary = "댓글 추가")
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "Created the comment.")
})
@PostMapping
public ResponseEntity<CommentResponseDto> addComment(
@RequestBody CommentRequestDto commentRequest,
@RequestParam Long todoId,
@RequestParam String userId
) {
Comment createdComment = commentService.addComment(commentRequest, todoId, userId);
CommentResponseDto responseDto = new CommentResponseDto(
createdComment.getCommentId(),
createdComment.getContent(),
createdComment.getUser().getId().toString(),
createdComment.getCreatedAt().toString()
);
return new ResponseEntity<>(responseDto, HttpStatus.CREATED);
}
@Operation(summary = "댓글 수정")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Updated the comment."),
@ApiResponse(responseCode = "404", description = "Comment not found.")
})
@PutMapping("/{commentId}")
public ResponseEntity<CommentResponseDto> updateComment(
@PathVariable Long commentId,
@RequestBody CommentRequestDto commentRequest,
@RequestParam Long todoId,
@RequestParam String userId
) {
// 댓글 업데이트
Comment updatedComment = commentService.updateComment(commentId, commentRequest, todoId, userId);
CommentResponseDto responseDto = new CommentResponseDto(
updatedComment.getCommentId(),
updatedComment.getContent(),
updatedComment.getUser().getId().toString(),
updatedComment.getCreatedAt().toString()
);
return new ResponseEntity<>(responseDto, HttpStatus.OK);
}
@Operation(summary = "댓글 삭제")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Deleted the comment."),
@ApiResponse(responseCode = "404", description = "Comment not found.")
})
@DeleteMapping("/{commentId}")
public ResponseEntity<String> deleteComment(@PathVariable Long commentId) {
// 현재 로그인한 사용자 ID 가져오기
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentUserId = authentication.getName(); // 사용자 ID 추출
// 댓글 삭제
commentService.deleteComment(commentId, currentUserId);
return new ResponseEntity<>("댓글이 삭제되었습니다.", HttpStatus.OK);
}
}
이렇게 Operation, ApiResponses를 추가해 설명을 더욱 강조했다.
// @RequestParam String userId
이걸 지우고 userid를 currentuserid로 바꾼다
@PostMapping
public ResponseEntity<CommentResponseDto> addComment(
@RequestBody CommentRequestDto commentRequest,
@RequestParam Long todoId,
@RequestParam String userId
) {
Comment createdComment = commentService.addComment(commentRequest, todoId, userId);
이녀석을
@PostMapping
public ResponseEntity<CommentResponseDto> addComment(
@RequestBody CommentRequestDto commentRequest,
@RequestParam Long todoId
// @RequestParam String userId
) {
// 현재 로그인한 사용자 ID 가져오기
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentUserId = authentication.getName();
Comment createdComment = commentService.addComment(commentRequest, todoId, currentUserId);