Skip to content

Commit 61f2f6e

Browse files
committed
[Feat]: 댓글 좋아요 추가, 삭제 기능 추가
# Conflicts: # back/src/main/java/com/back/domain/comment/repository/CommentRepository.java
1 parent bae6543 commit 61f2f6e

File tree

6 files changed

+83
-0
lines changed

6 files changed

+83
-0
lines changed

back/src/main/java/com/back/domain/comment/entity/Comment.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,14 @@ public void checkUser(Long userId) {
5858
public void updateContent(String content) {
5959
this.content = content;
6060
}
61+
62+
public void incrementLikeCount() {
63+
this.likeCount++;
64+
}
65+
66+
public void decrementLikeCount() {
67+
if (this.likeCount > 0) {
68+
this.likeCount--;
69+
}
70+
}
6171
}

back/src/main/java/com/back/domain/comment/repository/CommentRepository.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
package com.back.domain.comment.repository;
22

33
import com.back.domain.comment.entity.Comment;
4+
import jakarta.persistence.LockModeType;
45
import org.springframework.data.domain.Page;
56
import org.springframework.data.domain.Pageable;
67
import org.springframework.data.jpa.repository.JpaRepository;
8+
import org.springframework.data.jpa.repository.Lock;
79
import org.springframework.data.jpa.repository.Query;
810
import org.springframework.data.repository.query.Param;
911
import org.springframework.stereotype.Repository;
1012

13+
import java.util.Optional;
14+
1115
/**
1216
* 댓글 엔티티에 대한 데이터베이스 접근을 담당하는 JpaRepository.
1317
*/
@@ -17,4 +21,8 @@ public interface CommentRepository extends JpaRepository<Comment, Long> {
1721
Page<Comment> findCommentsByPostId(@Param("postId") Long postId, Pageable pageable);
1822

1923
int countByUserId(Long userId);
24+
25+
@Lock(LockModeType.PESSIMISTIC_WRITE)
26+
@Query("SELECT c FROM Comment c WHERE c.id = :commentId")
27+
Optional<Comment> findByIdWithLock(@Param("commentId") Long commentId);
2028
}

back/src/main/java/com/back/domain/like/controller/LikeController.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,20 @@ public ResponseEntity<Void> removeLike(@PathVariable Long postId, @Authenticatio
2828
likeService.removeLike(postId, cs.getUser().getId());
2929
return ResponseEntity.ok(null);
3030
}
31+
32+
@PostMapping("/{postId}/comments/{commentId}/likes")
33+
public ResponseEntity<Void> addCommentLike(@PathVariable Long postId,
34+
@PathVariable Long commentId,
35+
@AuthenticationPrincipal CustomUserDetails cs) {
36+
likeService.addCommentLike(cs.getUser().getId(), postId, commentId);
37+
return ResponseEntity.status(HttpStatus.CREATED).body(null);
38+
}
39+
40+
@DeleteMapping("/{postId}/comments/{commentId}/likes")
41+
public ResponseEntity<Void> removeCommentLike(@PathVariable Long postId,
42+
@PathVariable Long commentId,
43+
@AuthenticationPrincipal CustomUserDetails cs) {
44+
likeService.removeCommentLike(cs.getUser().getId(), postId, commentId);
45+
return ResponseEntity.ok(null);
46+
}
3147
}

back/src/main/java/com/back/domain/like/repository/CommentLikeRepository.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.back.domain.like.entity.CommentLike;
44
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.data.jpa.repository.Modifying;
56
import org.springframework.data.jpa.repository.Query;
67
import org.springframework.data.repository.query.Param;
78
import org.springframework.stereotype.Repository;
@@ -15,4 +16,10 @@
1516
public interface CommentLikeRepository extends JpaRepository<CommentLike, Long> {
1617
@Query("SELECT cl.comment.id FROM CommentLike cl WHERE cl.user.id = :userId AND cl.comment.id IN :commentIds")
1718
Set<Long> findLikedCommentsIdsByUserAndCommentIds(@Param("userId") Long userId, @Param("commentIds") Set<Long> commentIds);
19+
20+
boolean existsByCommentIdAndUserId(Long commentId, Long userId);
21+
22+
@Modifying
23+
@Query("DELETE FROM CommentLike cl WHERE cl.comment.id = :commentId AND cl.user.id = :userId")
24+
int deleteByCommentIdAndUserId(@Param("commentId") Long commentId, @Param("userId") Long userId);
1825
}

back/src/main/java/com/back/domain/like/service/LikeService.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.back.domain.like.service;
22

3+
import com.back.domain.comment.entity.Comment;
4+
import com.back.domain.comment.repository.CommentRepository;
5+
import com.back.domain.like.entity.CommentLike;
36
import com.back.domain.like.entity.PostLike;
47
import com.back.domain.like.repository.CommentLikeRepository;
58
import com.back.domain.like.repository.PostLikeRepository;
@@ -23,6 +26,7 @@ public class LikeService {
2326

2427
private final PostLikeRepository postLikeRepository;
2528
private final CommentLikeRepository commentLikeRepository;
29+
private final CommentRepository commentRepository;
2630
private final PostRepository postRepository;
2731
private final UserRepository userRepository;
2832

@@ -55,11 +59,48 @@ public void removeLike(Long postId, Long userId) {
5559
post.decrementLikeCount();
5660
}
5761

62+
@Transactional
63+
public void addCommentLike(Long userId, Long postId, Long commentId) {
64+
Comment comment = commentRepository.findByIdWithLock(commentId)
65+
.orElseThrow(() -> new ApiException(ErrorCode.COMMENT_NOT_FOUND));
66+
67+
if (commentLikeRepository.existsByCommentIdAndUserId(postId, userId)) {
68+
throw new ApiException(ErrorCode.COMMENT_ALREADY_LIKED);
69+
}
70+
71+
CommentLike commentLike = createCommentLike(comment, userId);
72+
73+
commentLikeRepository.save(commentLike);
74+
comment.incrementLikeCount();
75+
}
76+
77+
@Transactional
78+
public void removeCommentLike(Long userId, Long postId, Long commentId) {
79+
Comment comment = commentRepository.findByIdWithLock(commentId)
80+
.orElseThrow(() -> new ApiException(ErrorCode.COMMENT_NOT_FOUND));
81+
82+
boolean deleted = commentLikeRepository.deleteByCommentIdAndUserId(commentId, userId) > 0;
83+
84+
if (!deleted) {
85+
throw new ApiException(ErrorCode.LIKE_NOT_FOUND);
86+
}
87+
88+
comment.decrementLikeCount();
89+
}
90+
5891
private PostLike createPostLike(Post post, Long userId) {
5992
User userReference = userRepository.getReferenceById(userId);
6093
return PostLike.builder()
6194
.post(post)
6295
.user(userReference)
6396
.build();
6497
}
98+
99+
private CommentLike createCommentLike(Comment comment, Long userId) {
100+
User userReference = userRepository.getReferenceById(userId);
101+
return CommentLike.builder()
102+
.comment(comment)
103+
.user(userReference)
104+
.build();
105+
}
65106
}

back/src/main/java/com/back/global/exception/ErrorCode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public enum ErrorCode {
3434

3535
// Comment Errors
3636
COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "CM001", "Comment Not Found"),
37+
COMMENT_ALREADY_LIKED(HttpStatus.BAD_REQUEST, "CM002", "Comment Already Liked"),
3738

3839
// Session Errors
3940
SESSION_NOT_FOUND(HttpStatus.NOT_FOUND, "S001", "Session Not Found"),

0 commit comments

Comments
 (0)