#24 simple sns: 댓글 기능 api
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
package com.example.sns.controller;
|
||||
|
||||
import com.example.sns.controller.request.PostCommentRequest;
|
||||
import com.example.sns.controller.request.PostCreateRequest;
|
||||
import com.example.sns.controller.request.PostModifyRequest;
|
||||
import com.example.sns.controller.response.CommentResponse;
|
||||
import com.example.sns.controller.response.PostResponse;
|
||||
import com.example.sns.controller.response.Response;
|
||||
import com.example.sns.model.Post;
|
||||
@@ -66,4 +68,17 @@ public class PostController {
|
||||
return Response.success(postService.likeCount(postId));
|
||||
}
|
||||
|
||||
@PostMapping("/{postId}/comments")
|
||||
public Response<Void> comment(@PathVariable Integer postId,
|
||||
@RequestBody PostCommentRequest request,
|
||||
Authentication authentication) {
|
||||
postService.comment(postId, authentication.getName(), request.getComment());
|
||||
return Response.success();
|
||||
}
|
||||
|
||||
@GetMapping("/{postId}/comments")
|
||||
public Response<Page<CommentResponse>> commentList(@PathVariable Integer postId,
|
||||
Pageable pageable) {
|
||||
return Response.success(postService.getComments(postId, pageable).map(CommentResponse::fromComment));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ package com.example.sns.controller.request;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class PostCommentRequest {
|
||||
|
||||
private String comment;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.example.sns.controller.response;
|
||||
|
||||
import com.example.sns.model.Comment;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class CommentResponse {
|
||||
|
||||
private Integer id;
|
||||
private String comment;
|
||||
private String username;
|
||||
private Integer postId;
|
||||
|
||||
private Timestamp registeredAt;
|
||||
private Timestamp updatedAt;
|
||||
private Timestamp deletedAt;
|
||||
|
||||
public static CommentResponse fromComment(Comment comment) {
|
||||
return new CommentResponse(
|
||||
comment.getId(),
|
||||
comment.getComment(),
|
||||
comment.getUsername(),
|
||||
comment.getPostId(),
|
||||
comment.getRegisteredAt(),
|
||||
comment.getUpdatedAt(),
|
||||
comment.getDeletedAt()
|
||||
);
|
||||
}
|
||||
}
|
||||
34
simple_sns/src/main/java/com/example/sns/model/Comment.java
Normal file
34
simple_sns/src/main/java/com/example/sns/model/Comment.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package com.example.sns.model;
|
||||
|
||||
import com.example.sns.model.entity.CommentEntity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class Comment {
|
||||
|
||||
private Integer id;
|
||||
private String comment;
|
||||
private String username;
|
||||
private Integer postId;
|
||||
|
||||
private Timestamp registeredAt;
|
||||
private Timestamp updatedAt;
|
||||
private Timestamp deletedAt;
|
||||
|
||||
public static Comment fromEntity(CommentEntity entity) {
|
||||
return new Comment(
|
||||
entity.getId(),
|
||||
entity.getComment(),
|
||||
entity.getUser().getUsername(),
|
||||
entity.getPost().getId(),
|
||||
entity.getRegisteredAt(),
|
||||
entity.getUpdatedAt(),
|
||||
entity.getDeletedAt()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.example.sns.model.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.hibernate.annotations.SQLDelete;
|
||||
import org.hibernate.annotations.Where;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
@Table(name = "comments", indexes = {
|
||||
@Index(name = "post_id_idx", columnList = "post_id")
|
||||
})
|
||||
@Getter
|
||||
@Setter
|
||||
@SQLDelete(sql = "UPDATE comments SET deleted_at = NOW() where id=?")
|
||||
@Where(clause = "deleted_at IS NULL")
|
||||
public class CommentEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Integer id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "user_id")
|
||||
private UserEntity user;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "post_id")
|
||||
private PostEntity post;
|
||||
|
||||
@Column(name = "comment")
|
||||
private String comment;
|
||||
|
||||
private Timestamp registeredAt;
|
||||
private Timestamp updatedAt;
|
||||
|
||||
@Column(name = "deleted_at")
|
||||
private Timestamp deletedAt;
|
||||
|
||||
@PrePersist
|
||||
void registeredAt() {
|
||||
this.registeredAt = Timestamp.from(Instant.now());
|
||||
}
|
||||
|
||||
@PreUpdate
|
||||
void updatedAt() {
|
||||
this.updatedAt = Timestamp.from(Instant.now());
|
||||
}
|
||||
|
||||
public static CommentEntity of(UserEntity userEntity, PostEntity postEntity, String comment) {
|
||||
CommentEntity entity = new CommentEntity();
|
||||
entity.setUser(userEntity);
|
||||
entity.setPost(postEntity);
|
||||
entity.setComment(comment);
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.example.sns.repository;
|
||||
|
||||
import com.example.sns.model.entity.CommentEntity;
|
||||
import com.example.sns.model.entity.PostEntity;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface CommentEntityRepository extends JpaRepository<CommentEntity, Integer> {
|
||||
|
||||
Page<CommentEntity> findAllByPost(PostEntity post, Pageable pageable);
|
||||
}
|
||||
@@ -1,10 +1,13 @@
|
||||
package com.example.sns.service;
|
||||
|
||||
import com.example.sns.exception.SnsApplicationException;
|
||||
import com.example.sns.model.Comment;
|
||||
import com.example.sns.model.Post;
|
||||
import com.example.sns.model.entity.CommentEntity;
|
||||
import com.example.sns.model.entity.LikeEntity;
|
||||
import com.example.sns.model.entity.PostEntity;
|
||||
import com.example.sns.model.entity.UserEntity;
|
||||
import com.example.sns.repository.CommentEntityRepository;
|
||||
import com.example.sns.repository.LikeEntityRepository;
|
||||
import com.example.sns.repository.PostEntityRepository;
|
||||
import com.example.sns.repository.UserEntityRepository;
|
||||
@@ -23,37 +26,19 @@ public class PostService {
|
||||
private final PostEntityRepository postEntityRepository;
|
||||
private final UserEntityRepository userEntityRepository;
|
||||
private final LikeEntityRepository likeEntityRepository;
|
||||
private final CommentEntityRepository commentEntityRepository;
|
||||
|
||||
@Transactional
|
||||
public void create(String title, String body, String username) {
|
||||
UserEntity userEntity = userEntityRepository.findByUsername(username)
|
||||
.orElseThrow(
|
||||
() -> new SnsApplicationException(
|
||||
USER_NOT_FOUND,
|
||||
String.format("%s not founded", username)
|
||||
)
|
||||
);
|
||||
UserEntity userEntity = getUserEntityOrException(username);
|
||||
|
||||
postEntityRepository.save(PostEntity.of(title, body, userEntity));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Post modify(String title, String body, String username, Integer postId) {
|
||||
UserEntity userEntity = userEntityRepository.findByUsername(username)
|
||||
.orElseThrow(
|
||||
() -> new SnsApplicationException(
|
||||
USER_NOT_FOUND,
|
||||
String.format("%s not founded", username)
|
||||
)
|
||||
);
|
||||
|
||||
PostEntity postEntity = postEntityRepository.findById(postId)
|
||||
.orElseThrow(
|
||||
() -> new SnsApplicationException(
|
||||
POST_NOT_FOUND,
|
||||
String.format("%s not founded", postId)
|
||||
)
|
||||
);
|
||||
UserEntity userEntity = getUserEntityOrException(username);
|
||||
PostEntity postEntity = getPostEntityOrException(postId);
|
||||
|
||||
if (postEntity.getUser() != userEntity) {
|
||||
throw new SnsApplicationException(
|
||||
@@ -70,21 +55,8 @@ public class PostService {
|
||||
|
||||
@Transactional
|
||||
public void delete(String username, Integer postId) {
|
||||
UserEntity userEntity = userEntityRepository.findByUsername(username)
|
||||
.orElseThrow(
|
||||
() -> new SnsApplicationException(
|
||||
USER_NOT_FOUND,
|
||||
String.format("%s not founded", username)
|
||||
)
|
||||
);
|
||||
|
||||
PostEntity postEntity = postEntityRepository.findById(postId)
|
||||
.orElseThrow(
|
||||
() -> new SnsApplicationException(
|
||||
POST_NOT_FOUND,
|
||||
String.format("%s not founded", postId)
|
||||
)
|
||||
);
|
||||
UserEntity userEntity = getUserEntityOrException(username);
|
||||
PostEntity postEntity = getPostEntityOrException(postId);
|
||||
|
||||
if (postEntity.getUser() != userEntity) {
|
||||
throw new SnsApplicationException(
|
||||
@@ -101,33 +73,15 @@ public class PostService {
|
||||
}
|
||||
|
||||
public Page<Post> my(String username, Pageable pageable) {
|
||||
UserEntity userEntity = userEntityRepository.findByUsername(username)
|
||||
.orElseThrow(
|
||||
() -> new SnsApplicationException(
|
||||
USER_NOT_FOUND,
|
||||
String.format("%s not founded", username)
|
||||
)
|
||||
);
|
||||
UserEntity userEntity = getUserEntityOrException(username);
|
||||
|
||||
return postEntityRepository.findAllByUser(userEntity, pageable).map(Post::fromEntity);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void like(Integer postId, String username) {
|
||||
PostEntity postEntity = postEntityRepository.findById(postId)
|
||||
.orElseThrow(
|
||||
() -> new SnsApplicationException(
|
||||
POST_NOT_FOUND,
|
||||
String.format("%s not founded", postId)
|
||||
)
|
||||
);
|
||||
|
||||
UserEntity userEntity = userEntityRepository.findByUsername(username)
|
||||
.orElseThrow(
|
||||
() -> new SnsApplicationException(
|
||||
USER_NOT_FOUND,
|
||||
String.format("%s not founded", username)
|
||||
)
|
||||
);
|
||||
PostEntity postEntity = getPostEntityOrException(postId);
|
||||
UserEntity userEntity = getUserEntityOrException(username);
|
||||
|
||||
// check liked
|
||||
likeEntityRepository.findByUserAndPost(userEntity, postEntity)
|
||||
@@ -143,20 +97,42 @@ public class PostService {
|
||||
}
|
||||
|
||||
public int likeCount(Integer postId) {
|
||||
PostEntity postEntity = postEntityRepository.findById(postId)
|
||||
.orElseThrow(
|
||||
() -> new SnsApplicationException(
|
||||
POST_NOT_FOUND,
|
||||
String.format("%s not founded", postId)
|
||||
)
|
||||
);
|
||||
PostEntity postEntity = getPostEntityOrException(postId);
|
||||
|
||||
// count like
|
||||
return likeEntityRepository.countByPost(postEntity);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void comment(Integer postId, String username) {
|
||||
public void comment(Integer postId, String username, String comment) {
|
||||
PostEntity postEntity = getPostEntityOrException(postId);
|
||||
UserEntity userEntity = getUserEntityOrException(username);
|
||||
|
||||
commentEntityRepository.save(CommentEntity.of(userEntity, postEntity, comment));
|
||||
}
|
||||
|
||||
public Page<Comment> getComments(Integer postId, Pageable pageable) {
|
||||
PostEntity postEntity = getPostEntityOrException(postId);
|
||||
return commentEntityRepository.findAllByPost(postEntity, pageable).map(Comment::fromEntity);
|
||||
}
|
||||
|
||||
private PostEntity getPostEntityOrException(Integer postId) {
|
||||
return postEntityRepository.findById(postId)
|
||||
.orElseThrow(
|
||||
() -> new SnsApplicationException(
|
||||
POST_NOT_FOUND,
|
||||
String.format("%s not founded", postId)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private UserEntity getUserEntityOrException(String username) {
|
||||
return userEntityRepository.findByUsername(username)
|
||||
.orElseThrow(
|
||||
() -> new SnsApplicationException(
|
||||
USER_NOT_FOUND,
|
||||
String.format("%s not founded", username)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ public class PostControllerTest {
|
||||
@WithMockUser
|
||||
void 댓글작성시_게시글이_없는경우() throws Exception {
|
||||
|
||||
doThrow(new SnsApplicationException(ErrorCode.POST_NOT_FOUND)).when(postService).comment(any(), any());
|
||||
doThrow(new SnsApplicationException(ErrorCode.POST_NOT_FOUND)).when(postService).comment(any(), any(), any());
|
||||
|
||||
mockMvc.perform(post("/api/v1/posts/1/comments")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
|
||||
Reference in New Issue
Block a user