-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/feat/community' into dev-check
- Loading branch information
Showing
13 changed files
with
334 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
src/main/java/com/numberone/backend/domain/comment/controller/CommentController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package com.numberone.backend.domain.comment.controller; | ||
|
||
import com.numberone.backend.domain.comment.dto.request.CreateChildCommentRequest; | ||
import com.numberone.backend.domain.comment.dto.response.CreateChildCommentResponse; | ||
import com.numberone.backend.domain.comment.dto.response.GetCommentDto; | ||
import com.numberone.backend.domain.comment.service.CommentService; | ||
import io.swagger.v3.oas.annotations.Operation; | ||
import jakarta.validation.Valid; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
import java.net.URI; | ||
import java.util.List; | ||
|
||
@Slf4j | ||
@RequestMapping("api/comments") | ||
@RequiredArgsConstructor | ||
@RestController | ||
public class CommentController { | ||
|
||
private final CommentService commentService; | ||
|
||
@Operation(summary = "대댓글 작성 API", description = """ | ||
comment-id 는 부모 댓글의 id 입니다. | ||
article-id 와 comment-id 는 모두 path variable 으로 보내주세요! | ||
""") | ||
@PostMapping("{article-id}/{comment-id}") | ||
public ResponseEntity<CreateChildCommentResponse> createChildComment( | ||
@PathVariable("article-id") Long articleId, | ||
@PathVariable("comment-id") Long commentId, | ||
@RequestBody @Valid CreateChildCommentRequest request) { | ||
CreateChildCommentResponse response = commentService.createChildComment(articleId, commentId, request); | ||
return ResponseEntity.created( | ||
URI.create(String.format("/comments/%s/%s", articleId, commentId))) | ||
.body(response); | ||
} | ||
|
||
@Operation(summary = "해당 게시물에 달린 댓긂을 모두 조회하는 API 입니다.", description = """ | ||
해당 게시물에 달린 댓글을 계층 형태로 조회합니다. | ||
- Long commentId : 댓글 아이디 | ||
- Long parentCommentId : 부모 댓글의 야이디 (nullable) | ||
- List<GetCommentDto> childComments = new ArrayList<>() : 대댓글 리스트 | ||
- Integer likeCount : 해당 댓글의 좋아요 개수 | ||
- LocalDateTime createdAt : 해당 댓글의 생성 시각 | ||
- LocalDateTime modifiedAt : 해당 댓글의 마지막 수정 시각 | ||
- String content : 해당 댓글의 내용 | ||
- Long authorId : 해당 댓글의 작성자 아이디 | ||
- String authorNickName : 해당 댓글의 작성자 닉네임 | ||
- String authorProfileImageUrl : 해당 댓글 작성자의 프로필 사진 url | ||
댓글 작성자가 추후에 탈퇴하는 경우를 고려했는데, | ||
authorNickName 이 "알수없는 사용자" 로 변경되어 내려갑니다..! | ||
""") | ||
@GetMapping("{article-id}") | ||
public ResponseEntity<List<GetCommentDto>> getCommentsByArticle(@PathVariable("article-id") Long articleId){ | ||
List<GetCommentDto> response = commentService.getCommentsByArticle(articleId); | ||
return ResponseEntity.ok(response); | ||
} | ||
|
||
} |
15 changes: 15 additions & 0 deletions
15
...main/java/com/numberone/backend/domain/comment/dto/request/CreateChildCommentRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.numberone.backend.domain.comment.dto.request; | ||
|
||
import jakarta.validation.constraints.NotNull; | ||
import lombok.*; | ||
|
||
@ToString | ||
@Builder | ||
@Getter | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@AllArgsConstructor | ||
public class CreateChildCommentRequest { | ||
@NotNull | ||
private String content; | ||
|
||
} |
25 changes: 25 additions & 0 deletions
25
...in/java/com/numberone/backend/domain/comment/dto/response/CreateChildCommentResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.numberone.backend.domain.comment.dto.response; | ||
|
||
import com.numberone.backend.domain.comment.entity.CommentEntity; | ||
import lombok.*; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
@ToString | ||
@Builder | ||
@Getter | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@AllArgsConstructor | ||
public class CreateChildCommentResponse { | ||
|
||
private LocalDateTime createdAt; | ||
private Long commentId; | ||
|
||
public static CreateChildCommentResponse of (CommentEntity comment){ | ||
return CreateChildCommentResponse.builder() | ||
.createdAt(comment.getCreatedAt()) | ||
.commentId(comment.getId()) | ||
.build(); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,4 +20,5 @@ public static CreateCommentResponse of (CommentEntity comment){ | |
.commentId(comment.getId()) | ||
.build(); | ||
} | ||
|
||
} |
62 changes: 62 additions & 0 deletions
62
src/main/java/com/numberone/backend/domain/comment/dto/response/GetCommentDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package com.numberone.backend.domain.comment.dto.response; | ||
|
||
import com.fasterxml.jackson.annotation.JsonFormat; | ||
import com.numberone.backend.domain.article.entity.Article; | ||
import com.numberone.backend.domain.comment.entity.CommentEntity; | ||
import com.numberone.backend.domain.member.entity.Member; | ||
import com.querydsl.core.annotations.QueryProjection; | ||
import lombok.*; | ||
|
||
import java.time.LocalDateTime; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.Optional; | ||
|
||
@ToString | ||
@Builder | ||
@Getter | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@AllArgsConstructor | ||
public class GetCommentDto { | ||
|
||
private Long commentId; | ||
private Long parentCommentId; | ||
private List<GetCommentDto> childComments = new ArrayList<>(); | ||
private Integer likeCount; | ||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss a", timezone = "Asia/Seoul") | ||
private LocalDateTime createdAt; | ||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss a", timezone = "Asia/Seoul") | ||
private LocalDateTime modifiedAt; | ||
private String content; | ||
private Long authorId; | ||
private String authorNickName; | ||
private String authorProfileImageUrl; | ||
|
||
|
||
@QueryProjection | ||
public GetCommentDto(CommentEntity comment){ | ||
if(!Objects.isNull(comment.getParent())){ | ||
this.parentCommentId = comment.getParent().getId(); | ||
} | ||
this.commentId = comment.getId(); | ||
this.createdAt = comment.getCreatedAt(); | ||
this.modifiedAt = comment.getModifiedAt(); | ||
this.content = comment.getContent(); | ||
this.authorId = comment.getAuthorId(); | ||
this.likeCount = comment.getLikeCount(); | ||
} | ||
|
||
public void updateCommentInfo(Optional<Member> author){ | ||
author.ifPresentOrElse( | ||
a -> { | ||
this.authorNickName = a.getNickName(); | ||
this.authorProfileImageUrl = a.getProfileImageUrl(); | ||
}, | ||
() -> { | ||
this.authorNickName = "알 수 없는 사용자"; | ||
} | ||
); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 2 additions & 1 deletion
3
src/main/java/com/numberone/backend/domain/comment/repository/CommentRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
package com.numberone.backend.domain.comment.repository; | ||
|
||
import com.numberone.backend.domain.comment.entity.CommentEntity; | ||
import com.numberone.backend.domain.comment.repository.custom.CommentRepositoryCustom; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface CommentRepository extends JpaRepository<CommentEntity, Long> { | ||
public interface CommentRepository extends JpaRepository<CommentEntity, Long>, CommentRepositoryCustom { | ||
} |
10 changes: 10 additions & 0 deletions
10
.../java/com/numberone/backend/domain/comment/repository/custom/CommentRepositoryCustom.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.numberone.backend.domain.comment.repository.custom; | ||
|
||
import com.numberone.backend.domain.comment.dto.response.GetCommentDto; | ||
|
||
import java.util.List; | ||
|
||
public interface CommentRepositoryCustom { | ||
public List<GetCommentDto> findAllByArticle(Long articleId); | ||
|
||
} |
34 changes: 34 additions & 0 deletions
34
...a/com/numberone/backend/domain/comment/repository/custom/CommentRepositoryCustomImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package com.numberone.backend.domain.comment.repository.custom; | ||
|
||
import com.numberone.backend.domain.article.entity.QArticle; | ||
import com.numberone.backend.domain.comment.dto.response.GetCommentDto; | ||
import com.numberone.backend.domain.comment.dto.response.QGetCommentDto; | ||
import com.querydsl.jpa.impl.JPAQueryFactory; | ||
import jakarta.persistence.EntityManager; | ||
|
||
import java.util.List; | ||
|
||
import static com.numberone.backend.domain.article.entity.QArticle.article; | ||
import static com.numberone.backend.domain.comment.entity.QCommentEntity.commentEntity; | ||
|
||
public class CommentRepositoryCustomImpl implements CommentRepositoryCustom { | ||
private final JPAQueryFactory queryFactory; | ||
|
||
public CommentRepositoryCustomImpl(EntityManager em) { | ||
this.queryFactory = new JPAQueryFactory(em); | ||
} | ||
|
||
@Override | ||
public List<GetCommentDto> findAllByArticle(Long articleId) { | ||
return queryFactory.select(new QGetCommentDto(commentEntity)) | ||
.from(commentEntity) | ||
.leftJoin(commentEntity.parent) | ||
.fetchJoin() | ||
.where(commentEntity.article.id.eq(articleId)) | ||
.orderBy( | ||
commentEntity.parent.id.asc().nullsFirst(), | ||
commentEntity.createdAt.asc() | ||
) | ||
.fetch(); | ||
} | ||
} |
88 changes: 88 additions & 0 deletions
88
src/main/java/com/numberone/backend/domain/comment/service/CommentService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package com.numberone.backend.domain.comment.service; | ||
|
||
import com.numberone.backend.domain.article.entity.Article; | ||
import com.numberone.backend.domain.article.repository.ArticleRepository; | ||
import com.numberone.backend.domain.articleparticipant.entity.ArticleParticipant; | ||
import com.numberone.backend.domain.articleparticipant.repository.ArticleParticipantRepository; | ||
import com.numberone.backend.domain.comment.dto.request.CreateChildCommentRequest; | ||
import com.numberone.backend.domain.comment.dto.response.CreateChildCommentResponse; | ||
import com.numberone.backend.domain.comment.dto.response.GetCommentDto; | ||
import com.numberone.backend.domain.comment.entity.CommentEntity; | ||
import com.numberone.backend.domain.comment.repository.CommentRepository; | ||
import com.numberone.backend.domain.member.entity.Member; | ||
import com.numberone.backend.domain.member.repository.MemberRepository; | ||
import com.numberone.backend.domain.token.util.SecurityContextProvider; | ||
import com.numberone.backend.exception.notfound.NotFoundArticleException; | ||
import com.numberone.backend.exception.notfound.NotFoundCommentException; | ||
import com.numberone.backend.exception.notfound.NotFoundMemberException; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.util.*; | ||
|
||
@Slf4j | ||
@Transactional(readOnly = true) | ||
@RequiredArgsConstructor | ||
@Service | ||
public class CommentService { | ||
|
||
private final CommentRepository commentRepository; | ||
private final ArticleRepository articleRepository; | ||
private final ArticleParticipantRepository articleParticipantRepository; | ||
private final MemberRepository memberRepository; | ||
|
||
@Transactional | ||
public CreateChildCommentResponse createChildComment( | ||
Long articleId, | ||
Long parentCommentId, | ||
CreateChildCommentRequest request) { | ||
|
||
String principal = SecurityContextProvider.getAuthenticatedUserEmail(); | ||
Member member = memberRepository.findByEmail(principal) | ||
.orElseThrow(NotFoundMemberException::new); | ||
Article article = articleRepository.findById(articleId) | ||
.orElseThrow(NotFoundArticleException::new); | ||
CommentEntity parentComment = commentRepository.findById(parentCommentId) | ||
.orElseThrow(NotFoundCommentException::new); | ||
|
||
CommentEntity childComment = commentRepository.save(new CommentEntity(request.getContent(), article, member)); | ||
childComment.updateParent(parentComment); | ||
|
||
articleParticipantRepository.save(new ArticleParticipant(article, member)); | ||
|
||
return CreateChildCommentResponse.of(childComment); | ||
} | ||
|
||
public List<GetCommentDto> getCommentsByArticle(Long articleId) { | ||
Article article = articleRepository.findById(articleId) | ||
.orElseThrow(NotFoundArticleException::new); | ||
List<GetCommentDto> comments = commentRepository.findAllByArticle(article.getId()); | ||
|
||
// 계층 구조로 변환 (추후 리팩토링 필요) | ||
List<GetCommentDto> result = new ArrayList<>(); | ||
Map<Long, GetCommentDto> map = new HashMap<>(); | ||
comments.forEach( | ||
comment -> { | ||
CommentEntity commentEntity = commentRepository.findById(comment.getCommentId()) | ||
.orElseThrow(NotFoundCommentException::new); | ||
Optional<Member> author = memberRepository.findById(commentEntity.getAuthorId()); | ||
comment.updateCommentInfo(author); | ||
|
||
map.put(comment.getCommentId(), comment); | ||
|
||
if (comment.getParentCommentId() != null){ | ||
GetCommentDto parentComment = map.get(comment.getParentCommentId()); | ||
List<GetCommentDto> childComments = parentComment.getChildComments(); | ||
childComments.add(comment); | ||
} else { | ||
result.add(comment); | ||
} | ||
} | ||
); | ||
|
||
return result; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
src/main/java/com/numberone/backend/exception/notfound/NotFoundCommentException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.numberone.backend.exception.notfound; | ||
|
||
import static com.numberone.backend.exception.context.CustomExceptionContext.NOT_FOUND_COMMENT; | ||
|
||
public class NotFoundCommentException extends NotFoundException { | ||
public NotFoundCommentException(){ | ||
super(NOT_FOUND_COMMENT); | ||
} | ||
} |