자 이제 Post에 댓글에 작성 기능을 만들것이다.
앞으로는 편의를 위해 Post를 게시글이라고 하겠다.
(개인적으로 Post에 댓글보다는 게시글에 댓글이 더 정감이 간다.)
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Builder
public class Comment extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String comment;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id") //외래키 : DB에 해당 명으로 컬럼설정
private User user;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_id") //DB에 해당 명으로 컬럼설정
private Post post;
}
Authentication에서 UserName을 가져와 사용한다.
게시물에 댓글을 달것이여서 PostId를 PathVariable로 받는다.
//댓글 작성
@PostMapping("/{postsId}/comments")
@ApiOperation(value = "댓글 작성기능",notes = "로그인 한 사용자가 댓글 작성")
//댓글 작성은 로그인 한 사람만 쓸 수 있습니다.
public Response<CommentResponse> write(@PathVariable Long postsId, @RequestBody CommentRequest commentRequest,Authentication authentication) {
log.info("userName" + authentication.getName());
return Response.success(commentService.write(postsId, authentication.getName(),commentRequest));
}
@AllArgsConstructor
@Getter
public class PostRequest {
private String title;
private String body;
public Post toEntity(User user) {
return Post.builder()
.title(this.title)
.body(this.body)
.user(user)
.build();
}
}
@AllArgsConstructor
@Getter
@Builder
public class CommentResponse {
private Long id;
private String comment;
private String userName;
private Long postId;
private LocalDateTime createdAt;
private LocalDateTime lastModifiedAt;
public static CommentResponse fromEntity(Comment comment) {
return CommentResponse.builder()
.id(comment.getId())
.comment(comment.getComment())
.userName(comment.getUser().getUserName())
.postId(comment.getPost().getId())
.createdAt(comment.getCreatedAt())
.lastModifiedAt(comment.getLastModifiedAt())
.build();
}
}
Conmmet는 우선 User가 저장되어야 하니, Authentication에서 받아온 username을 통해 User를 찾는다.
Post에 댓글을 달것이니 Post도 찾는다.
그리고 user와 post가 모두 존재한다면 Comment를 dto로 받아온 정보와 같이 저장한다.
@Service
@RequiredArgsConstructor
@Transactional
@Slf4j
public class CommentService {
private final CommentRepository commentRepository;
private final AlarmRepository alarmRepository;
private final PostService postService;
private final UserService userService;
public CommentResponse write(Long postId,String userName ,CommentRequest commentRequest) {
User user = userService.getUserByUserName(userName);
Post post = postService.getPostByPostId(postId);
// 저장
Comment comment = commentRepository.save(commentRequest.toEntity(user, post));
}
}
여기서 특이한점은 Post와 User를 확인하기위해 Repository를 DI한게 아니라 Service를 DI했다는 것이다.
프로젝트를 진행하면서 코드를 어떻게 깔끔하게 작성할지에 대한 고민을 해보았다.
처음에는 각 Repository를 DI해서 중복되는 메서드들을 공통으로 묶어 처리했는데, 지금 프로젝트의 경우 공통으로 묶는 과정도 중복으로 처리해야하는 상황이 생겼다.
즉 매번 어떠한 기능의 Service를 만들때마다, 각각 필요한 Repository를 가져와햐하고, 그다음 이미 했던 공통처리를 다시해야 하는 것이다.
그래서 아예 Service를 DI했다. 이렇게 하면 Service에서 공통으로 묶었던 메소드를 바로 사용할 수 있어서 이미 진행했던 로직을 다시 구현하지 않아도 되었다.
하지만, Service레이어에서 Repository 말고 다른 Service를 사용하는것이 좋은 코드인지는 아직 모르겠다.
아직은 단점보다는 장점이 훨씬많아서 Service를 DI해서 사용하고 있다.
나중에가면 불편한게 생길지도 모르겠다.
public interface CommentRepository extends JpaRepository<Comment, Long> {
Page<Comment> findByPostId(Long id, Pageable pageable);
}
이제 댓글을 작성 할 수 있다.
Swagger를 통해 확인해 보자.



That's simple and accurate https://slopeonline.online/