diff --git a/src/main/java/com/handongapp/cms/dto/v1/CommentDto.java b/src/main/java/com/handongapp/cms/dto/v1/CommentDto.java index faadd668..f7664d0c 100644 --- a/src/main/java/com/handongapp/cms/dto/v1/CommentDto.java +++ b/src/main/java/com/handongapp/cms/dto/v1/CommentDto.java @@ -1,6 +1,7 @@ package com.handongapp.cms.dto.v1; import com.handongapp.cms.domain.TbComment; +import com.handongapp.cms.domain.TbCommentOfCategory; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; import lombok.*; @@ -23,9 +24,12 @@ public static class Response { private final String content; private final LocalDateTime createdAt; private final LocalDateTime updatedAt; + private final String categorySlug; + private final String categoryLabel; + private final String categoryEmoji; // Constructor for final fields - public Response(String id, String targetId, String userId, String categoryId, String content, LocalDateTime createdAt, LocalDateTime updatedAt) { + public Response(String id, String targetId, String userId, String categoryId, String content, LocalDateTime createdAt, LocalDateTime updatedAt, String categorySlug, String categoryLabel, String categoryEmoji) { this.id = id; this.targetId = targetId; this.userId = userId; @@ -33,8 +37,14 @@ public Response(String id, String targetId, String userId, String categoryId, St this.content = content; this.createdAt = createdAt; this.updatedAt = updatedAt; + this.categorySlug = categorySlug; + this.categoryLabel = categoryLabel; + this.categoryEmoji = categoryEmoji; } + /** + * TbComment 엔티티만 사용하여 Response 객체 생성 + */ public static Response from(TbComment entity) { if (entity == null) return null; return new Response( @@ -44,7 +54,29 @@ public static Response from(TbComment entity) { entity.getCategoryId(), entity.getContent(), entity.getCreatedAt(), - entity.getUpdatedAt() + entity.getUpdatedAt(), + null, // categorySlug + null, // categoryLabel + null // categoryEmoji + ); + } + + /** + * TbComment 엔티티와 TbCommentOfCategory 엔티티를 사용하여 Response 객체 생성 + */ + public static Response from(TbComment entity, TbCommentOfCategory category) { + if (entity == null) return null; + return new Response( + entity.getId(), + entity.getTargetId(), + entity.getUserId(), + entity.getCategoryId(), + entity.getContent(), + entity.getCreatedAt(), + entity.getUpdatedAt(), + category != null ? category.getSlug() : null, + category != null ? category.getLabel() : null, + category != null ? category.getEmoji() : null ); } } diff --git a/src/main/java/com/handongapp/cms/repository/CommentRepository.java b/src/main/java/com/handongapp/cms/repository/CommentRepository.java index ec90b63b..813c53b1 100644 --- a/src/main/java/com/handongapp/cms/repository/CommentRepository.java +++ b/src/main/java/com/handongapp/cms/repository/CommentRepository.java @@ -26,4 +26,20 @@ List findCommentsByCriteria( @Param("userId") String userId, @Param("deletedStatus") String deletedStatus ); + + /** + * 코멘트를 조회하면서 코멘트 카테고리 정보를 LEFT JOIN하여 함께 가져오는 쿼리 + * 카테고리가 없는 경우에도 코멘트는 조회되어야 하기 때문에 LEFT JOIN 사용 + */ + @Query("SELECT c, cat FROM TbComment c " + + "LEFT JOIN TbCommentOfCategory cat ON c.categoryId = cat.id " + + "WHERE ((:targetIds) IS NULL OR c.targetId IN (:targetIds)) AND " + + "(:userId IS NULL OR c.userId = :userId) AND " + + "c.deleted = :deletedStatus " + + "ORDER BY c.createdAt DESC") + List findCommentsWithCategoriesByCriteria( + @Param("targetIds") List targetIds, + @Param("userId") String userId, + @Param("deletedStatus") String deletedStatus + ); } diff --git a/src/main/java/com/handongapp/cms/service/impl/CommentServiceImpl.java b/src/main/java/com/handongapp/cms/service/impl/CommentServiceImpl.java index 4d877796..b9761f62 100644 --- a/src/main/java/com/handongapp/cms/service/impl/CommentServiceImpl.java +++ b/src/main/java/com/handongapp/cms/service/impl/CommentServiceImpl.java @@ -1,8 +1,10 @@ package com.handongapp.cms.service.impl; import com.handongapp.cms.domain.TbComment; +import com.handongapp.cms.domain.TbCommentOfCategory; import com.handongapp.cms.dto.v1.CommentDto; import com.handongapp.cms.repository.CommentRepository; +import com.handongapp.cms.repository.CommentOfCategoryRepository; import com.handongapp.cms.mapper.CustomQueryMapper; import com.handongapp.cms.service.CommentService; import com.handongapp.cms.exception.data.NotFoundException; @@ -24,6 +26,7 @@ public class CommentServiceImpl implements CommentService { private final CustomQueryMapper customQueryMapper; private final CommentRepository commentRepository; + private final CommentOfCategoryRepository commentOfCategoryRepository; private static final String DELETED_STATUS_NO = "N"; private static final String DELETED_STATUS_YES = "Y"; @@ -34,7 +37,14 @@ public CommentDto.Response create(String userId, CommentDto.CreateRequest req) { TbComment entity = req.toEntity(userId); TbComment savedComment = commentRepository.save(entity); - return CommentDto.Response.from(savedComment); + + // 카테고리 정보를 함께 반환하기 위해 카테고리 조회 + TbCommentOfCategory category = null; + if (savedComment.getCategoryId() != null) { + category = commentOfCategoryRepository.findById(savedComment.getCategoryId()).orElse(null); + } + + return CommentDto.Response.from(savedComment, category); } @Override @@ -48,7 +58,14 @@ public CommentDto.Response update(String commentId, String userId, CommentDto.Up } req.applyTo(entity); - return CommentDto.Response.from(entity); + + // 카테고리 정보를 함께 반환하기 위해 카테고리 조회 + TbCommentOfCategory category = null; + if (entity.getCategoryId() != null) { + category = commentOfCategoryRepository.findById(entity.getCategoryId()).orElse(null); + } + + return CommentDto.Response.from(entity, category); } @Override @@ -86,10 +103,21 @@ public List searchComments( targetIdsForQuery = resolveTargetIds(resolvedCourseId); } - List comments = commentRepository.findCommentsByCriteria(targetIdsForQuery, resolvedUserId, DELETED_STATUS_NO); - - return comments.stream() - .map(CommentDto.Response::from) + // 카테고리 정보를 함께 조회하는 조인 쿼리 사용 + List commentsWithCategories = commentRepository.findCommentsWithCategoriesByCriteria( + targetIdsForQuery, resolvedUserId, DELETED_STATUS_NO); + + return commentsWithCategories.stream() + .map(result -> { + if (result == null || result.length == 0) { + return null; + } + TbComment comment = (TbComment) result[0]; + TbCommentOfCategory category = (result.length > 1 && result[1] != null) ? + (TbCommentOfCategory) result[1] : null; + return CommentDto.Response.from(comment, category); + }) + .filter(response -> response != null) .collect(Collectors.toList()); } @@ -182,6 +210,4 @@ private List resolveTargetIds(String courseId) { private List resolveTargetIdsByNodeGroup(String nodeGroupId) { return isNotEmpty(nodeGroupId) ? customQueryMapper.findTargetIdsByNodeGroupId(nodeGroupId) : null; } - - }