Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.jiwon.mylog.domain.comment.controller;

import com.jiwon.mylog.domain.comment.service.CommentService;
import com.jiwon.mylog.global.common.entity.PageResponse;
import com.jiwon.mylog.global.security.auth.annotation.LoginUser;
import com.jiwon.mylog.domain.comment.dto.request.CommentCreateRequest;
import com.jiwon.mylog.domain.comment.dto.request.CommentUpdateRequest;
Expand All @@ -10,9 +11,12 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand Down Expand Up @@ -78,4 +82,15 @@ public ResponseEntity<Void> deleteComment(
commentService.deleteComment(userId, postId, commentId);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}

@GetMapping("/posts/{postId}/comments")
@Operation(
summary = "게시글에 해당하는 댓글 목록 조회 (페이징)"
)
public ResponseEntity<PageResponse> getComments(
@PathVariable("postId") Long postId,
@PageableDefault(size = 10, page = 0) Pageable pageable) {
PageResponse response = commentService.getComments(postId, pageable);
return ResponseEntity.ok(response);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ public class CommentCreateRequest {
@Size(max = 500, message = "댓글은 최대 500자까지 입력할 수 있습니다.")
private String content;

@NotNull(message = "게시글 공개 범위를 지정해주세요.")
@NotNull(message = "공개 범위를 지정해주세요.")
private String visibility;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import java.util.Optional;

@Repository
public interface CommentRepository extends JpaRepository<Comment, Long> {
public interface CommentRepository extends JpaRepository<Comment, Long>, CommentRepositoryCustom {
@Query("select c from Comment c join fetch c.user u where c.id = :commentId")
Optional<Comment> findById(@Param("commentId") Long commentId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.jiwon.mylog.domain.comment.repository;

import com.jiwon.mylog.domain.comment.dto.response.CommentResponse;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface CommentRepositoryCustom {
Page<CommentResponse> findByPostId(Long postId, Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.jiwon.mylog.domain.comment.repository;

import com.jiwon.mylog.domain.comment.dto.response.CommentResponse;
import com.jiwon.mylog.domain.comment.entity.QComment;
import com.jiwon.mylog.domain.image.entity.QProfileImage;
import com.jiwon.mylog.domain.user.dto.response.UserResponse;
import com.jiwon.mylog.domain.user.entity.QUser;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;

@RequiredArgsConstructor
@Repository
public class CommentRepositoryImpl implements CommentRepositoryCustom {

private static final QComment COMMENT = QComment.comment;
private static final QUser USER = QUser.user;
private static final QProfileImage PROFILE_IMAGE = QProfileImage.profileImage;
private final JPAQueryFactory jpaQueryFactory;

@Override
public Page<CommentResponse> findByPostId(Long postId, Pageable pageable) {
BooleanBuilder conditions = new BooleanBuilder()
.and(postIdEq(postId));

List<CommentResponse> comments = jpaQueryFactory
.select(Projections.constructor(CommentResponse.class,
COMMENT.id,
COMMENT.parent.id,
COMMENT.depth,
COMMENT.visibility,
COMMENT.commentStatus,
Expressions.cases()
.when(COMMENT.deletedAt.isNotNull()).then("삭제된 댓글입니다.")
.otherwise(COMMENT.content),
Projections.constructor(UserResponse.class,
USER.id,
USER.username,
USER.bio,
PROFILE_IMAGE.fileKey.coalesce(""),
USER.status
),
COMMENT.createdAt,
COMMENT.updatedAt,
COMMENT.deletedAt
)
)
.from(COMMENT)
.leftJoin(COMMENT.user, USER)
.leftJoin(USER.profileImage, PROFILE_IMAGE)
.where(conditions)
.orderBy(COMMENT.createdAt.desc(), COMMENT.id.desc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();

Long total = createCountQuery(conditions);
return new PageImpl<>(comments, pageable, total);
}

private Long createCountQuery(BooleanBuilder builder) {
Long count = jpaQueryFactory
.select(COMMENT.count())
.from(COMMENT)
.where(builder)
.fetchOne();

return count != null ? count : 0L;
}

private BooleanExpression postIdEq(Long postId) {
return postId != null ? COMMENT.post.id.eq(postId) : null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@
import com.jiwon.mylog.domain.event.dto.comment.CommentDeletedEvent;
import com.jiwon.mylog.domain.post.entity.Post;
import com.jiwon.mylog.domain.user.entity.User;
import com.jiwon.mylog.global.common.entity.PageResponse;
import com.jiwon.mylog.global.common.error.ErrorCode;
import com.jiwon.mylog.global.common.error.exception.ForbiddenException;
import com.jiwon.mylog.global.common.error.exception.NotFoundException;
import com.jiwon.mylog.domain.post.repository.PostRepository;
import com.jiwon.mylog.domain.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -31,7 +33,6 @@ public class CommentService {
private final PostRepository postRepository;
private final CommentRepository commentRepository;

@CacheEvict(value = "post::detail", key = "#postId")
@Transactional
public CommentResponse createComment(Long userId, Long postId, CommentCreateRequest request) {

Expand Down Expand Up @@ -64,7 +65,6 @@ public CommentResponse createComment(Long userId, Long postId, CommentCreateRequ
return CommentResponse.fromComment(savedComment);
}

@CacheEvict(value = "post::detail", key = "#postId")
@Transactional
public CommentResponse updateComment(Long userId, Long postId, Long commentId, CommentUpdateRequest request) {
Comment comment = getComment(commentId);
Expand All @@ -73,7 +73,6 @@ public CommentResponse updateComment(Long userId, Long postId, Long commentId, C
return CommentResponse.fromComment(comment);
}

@CacheEvict(value = "post::detail", key = "#postId")
@Transactional
public void deleteComment(Long userId, Long postId, Long commentId) {
Comment comment = getComment(commentId);
Expand All @@ -94,6 +93,18 @@ public void deleteComment(Long userId, Long postId, Long commentId) {
comment.delete();
}

@Transactional(readOnly = true)
public PageResponse getComments(Long postId, Pageable pageable) {
Page<CommentResponse> commentPage = commentRepository.findByPostId(postId, pageable);
return PageResponse.from(
commentPage.getContent(),
commentPage.getNumber(),
commentPage.getSize(),
commentPage.getTotalPages(),
commentPage.getTotalElements()
);
}

private Comment getComment(Long commentId) {
return commentRepository.findById(commentId)
.orElseThrow(() -> new NotFoundException(ErrorCode.NOT_FOUND_COMMENT));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.jiwon.mylog.domain.post.controller;

import com.jiwon.mylog.domain.post.dto.response.PostNavigationResponse;
import com.jiwon.mylog.domain.post.service.PostService;
import com.jiwon.mylog.domain.post.service.PostViewService;
import com.jiwon.mylog.global.security.auth.annotation.AllUser;
Expand Down Expand Up @@ -115,6 +114,18 @@ public ResponseEntity<PostDetailResponse> getPost(
return new ResponseEntity<>(response, HttpStatus.OK);
}

@GetMapping("/posts/{postId}/related-post")
@Operation(
summary = "postId와 동일한 카테고리에 해당하는 게시글 목록 조회"
)
public ResponseEntity<PageResponse> getRelatedPosts(
@PathVariable("postId") Long postId,
@RequestParam(required = false) Integer page,
@RequestParam(defaultValue = "5") int size) {
PageResponse response = postService.getRelatedPosts(postId, page, size);
return ResponseEntity.ok(response);
}

@GetMapping("/posts")
public ResponseEntity<PageResponse> getPosts(
@PageableDefault(size = 10, page = 0,
Expand All @@ -123,23 +134,6 @@ public ResponseEntity<PageResponse> getPosts(
return new ResponseEntity<>(response, HttpStatus.OK);
}

@GetMapping("/posts/{postId}/navigation")
@Operation(
summary = "현재 게시글의 정보(카테고리 ID, 카테고리 내에서의 현재 page, offset)를 획득한다."
)
public ResponseEntity<PostNavigationResponse> getPostNavigation(@PathVariable("postId") Long postId) {
PostNavigationResponse response = postService.getPostNavigation(postId);
return ResponseEntity.ok(response);
}

@GetMapping("/categories/{categoryId}/posts")
public ResponseEntity<PageResponse> getCategorizedPosts(
@PathVariable("categoryId") Long categoryId,
@RequestParam Long userId,
@PageableDefault(size = 5, sort = "createdAt", direction = Direction.DESC) Pageable pageable) {
PageResponse response = postService.getCategorizedPosts(categoryId, userId, pageable);
return ResponseEntity.ok(response);
}

@GetMapping("/users/{userId}/categories/{categoryId}/posts")
@Operation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import com.jiwon.mylog.domain.post.entity.PostType;
import com.jiwon.mylog.global.common.enums.Visibility;
import com.jiwon.mylog.domain.category.dto.response.CategoryResponse;
import com.jiwon.mylog.domain.comment.dto.response.CommentResponse;
import com.jiwon.mylog.domain.post.entity.PostStatus;
import com.jiwon.mylog.domain.tag.dto.response.TagResponse;
import com.jiwon.mylog.domain.user.dto.response.UserResponse;
Expand Down Expand Up @@ -35,7 +34,6 @@ public class PostDetailResponse {
private UserResponse user;
private CategoryResponse category;
private List<TagResponse> tags;
private List<CommentResponse> comments;
private RelatedPostResponse previousPost;
private RelatedPostResponse nextPost;

Expand Down Expand Up @@ -71,9 +69,6 @@ public static PostDetailResponse fromPost(Post post) {
.createdAt(post.getCreatedAt())
.pinned(post.isPinned())
.type(post.getType())
.comments(post.getComments().stream()
.map(comment -> CommentResponse.fromComment(comment))
.toList())
.build();
}

Expand All @@ -86,8 +81,7 @@ public void setViews(int views) {
this.views = views;
}

public void setTagsAndComments(List<TagResponse> tags, List<CommentResponse> comments) {
public void setTags(List<TagResponse> tags) {
this.tags = tags;
this.comments = comments;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.jiwon.mylog.domain.post.dto.response;

import java.time.LocalDateTime;
import lombok.Builder;

@Builder
public record PostRelationData(
Long userId,
Long categoryId,
LocalDateTime createdAt
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.jiwon.mylog.domain.post.dto.response.MainPostResponse;
import com.jiwon.mylog.domain.post.dto.response.PostDetailResponse;
import com.jiwon.mylog.domain.post.dto.response.PostNavigationResponse;
import com.jiwon.mylog.domain.post.dto.response.PostSummaryResponse;
import com.jiwon.mylog.domain.post.dto.response.RelatedPostResponse;
import com.jiwon.mylog.domain.user.dto.response.UserActivityResponse;
Expand All @@ -24,7 +23,5 @@ public interface PostRepositoryCustom {

List<UserActivityResponse> findUserActivities(Long userId, LocalDate start, LocalDate end);

PostNavigationResponse findPostNavigation(Long postId);

Page<RelatedPostResponse> findCategorizedPosts(Long categoryId, Long userId, Pageable pageable);
Page<RelatedPostResponse> findRelatedPosts(Long postId, Integer page, int size);
}
Loading