- 생성한 일정에 댓글을 남길 수 있습니다.
- 댓글과 일정은 연관관계를 가집니다.
- 댓글을 저장, 조회, 수정, 삭제할 수 있습니다.
- 댓글은 아래와 같은 필드를 가집니다.
- 댓글 내용, 작성일, 수정일, 작성 유저명 필드
댓글은 특정 게시글에 남기는 것이므로 컨트롤러에서 요청을 받을 때 일정의 고유값인 todoId를 같이 받도록하였다.
Controller
@RestController
@RequestMapping("/api/comment")
@RequiredArgsConstructor
public class CommentController {
private final CommentService cmtService;
@GetMapping("/{todoId}")
public ResponseEntity<List<CommentResponseDto>> findByTodoId(@PathVariable("todoId") Long todoId){
return ResponseEntity.ok(cmtService.findByTodoId(todoId));
}
@PostMapping("/{todoId}")
public ResponseEntity<CommentResponseDto> createComment(@RequestBody @Valid CommentRequestDto commentReqDto, @PathVariable("todoId") Long todoId){
CommentResponseDto createComment = cmtService.createComment(commentReqDto,todoId);
return ResponseEntity.status(HttpStatus.CREATED).body(createComment);
}
@PutMapping("/{id}")
public void modifyComment(@PathVariable("id") Long id, String content){
cmtService.modifyComment(id,content);
}
@DeleteMapping("/{id}")
public void deleteComment(@PathVariable("id") Long id){
cmtService.deleteComment(id);
}
}
Entity
@Entity
@Table(name ="comment")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class Comment extends AuditingDate{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String content;
@Column(nullable = false, name = "user_name")
private String userName;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "todo_id")
private Todo todo;
public static Comment from(String content, String userName, Todo todo) {
Comment comment = new Comment();
comment.init(content, userName, todo);
return comment;
}
private void init(String content, String userName, Todo todo) {
this.content = content;
this.userName = userName;
this.todo = todo;
}
public void modify(String content) {
this.content = content;
}
}
AuditingDate
@MappedSuperclass
@Getter
@EntityListeners(AuditingEntityListener.class)
public abstract class AuditingDate {
@CreatedDate
@Temporal(TemporalType.TIMESTAMP)
private LocalDateTime createdAt;
@LastModifiedDate
@Temporal(TemporalType.TIMESTAMP)
private LocalDateTime modifiedAt;
}
지금까지 만든 일정, 댓글 엔티티와 아직 만들지 않은 매니저, 유저 엔티티에는
모두 작성일과 수정일이 필요로하기 때문에 AuditingEntityListener를 이용하여
코드의 중복 없이 각각 엔티티에 수정일과 작성일을 자동으로 넣어주었다.
Auditing에 대해서는 다른 포스터에서 따로 정리해보려고한다.
Service
@Service
@RequiredArgsConstructor
public class CommentService {
private final CommentRepository cmtRepo;
private final TodoRepository todoRepo;
@Transactional
public CommentResponseDto createComment(CommentRequestDto commentReqDto, Long todoId) {
Todo todo = isValidTodoId(todoId);
todoRepo.updateCommentCount(todo.getCommentCount()+1, todoId);
Comment comment = Comment.from(commentReqDto.getContent(),commentReqDto.getUserName(),todo);
return new CommentResponseDto(cmtRepo.save(comment));
}
public List<CommentResponseDto> findByTodoId(Long todoId) {
isValidTodoId(todoId);
return cmtRepo.findByTodoId(todoId).stream().map(CommentResponseDto :: new).toList();
}
@Transactional
public void modifyComment(Long id, String content) {
Comment findComment = isValidComment(id);
findComment.modify(content);
}
@Transactional
public void deleteComment(Long id) {
isValidComment(id);
cmtRepo.deleteById(id);
}
private Todo isValidTodoId(Long todoId) {
return todoRepo.findById(todoId).orElseThrow(()-> new CustomException(ErrorCode.NOT_TODO_ID));
}
private Comment isValidComment(Long commentId) {
return cmtRepo.findById(commentId).orElseThrow(() -> new CustomException(ErrorCode.NOT_COMMENT_ID));
}
}
트러블슈팅
전체 일정 조회 시 각 게시글마다 댓글의 수도 같이 조회하라는 요구사항이 있어서 댓글을 하나 추가할 때마다
해당하는 게시물의 댓글 count수를 한개씩 올려주었다.
다만 처음에는 댓글 수를 올려 줄 때 Todo에 변화를 주어 더티체킹을 이용하여 카운트 수를 올려줬었는데 그럴 때마다 수정일도 같이
최근일로 수정되는 이슈가 발생하였다. 이걸 어떻게 할까 하며 구글링을 하다가 @Query 어노테이션을 이용하여
직접 쿼리문을 작성하는 방법이 있다는걸 알았다. 그래서 더티체킹으로 하던 방식이 아닌 직접
todoRepository에 쿼리문을 작성하여 수정하는 방식으로 고쳤더니 댓글을 추가하며 카운트 수를 올려도 수정일은 바뀌지않았다 !!
public interface TodoRepository extends JpaRepository<Todo,Long> {
@Modifying
@Query("update Todo t set t.commentCount = :commentCount where t.id = :id")
void updateCommentCount(int commentCount, Long id);
}
'TIL' 카테고리의 다른 글
페이징 조회 - Pageble / PageRequest (0) | 2024.10.15 |
---|---|
JPA - Entity (1) | 2024.10.15 |
JPA - 일정 CRUD (1) | 2024.10.13 |
JPA (1) | 2024.10.10 |
IoC & DI (1) | 2024.10.07 |