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
@@ -0,0 +1,10 @@
package com.example.be.apiPayload.exception.handler;

import com.example.be.apiPayload.code.BaseErrorCode;
import com.example.be.apiPayload.exception.GeneralException;

public class PostHandler extends GeneralException {
public PostHandler(BaseErrorCode code) {
super(code);
}
}
3 changes: 3 additions & 0 deletions src/main/java/com/example/be/domain/Comment.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,7 @@ public class Comment {

@OneToMany(mappedBy = "topParent", cascade = CascadeType.ALL)
private List<Comment> children = new ArrayList<>(); // 직계 자식

@OneToMany(mappedBy = "comment", cascade = CascadeType.ALL, orphanRemoval = true)
private List<CommentLike> likes = new ArrayList<>();
}
32 changes: 32 additions & 0 deletions src/main/java/com/example/be/domain/CommentLike.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.example.be.domain;

import jakarta.persistence.*;
import lombok.*;

import java.time.LocalDateTime;

@Entity
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(uniqueConstraints = {
@UniqueConstraint(columnNames = {"user_id", "comment_id"})
})
public class CommentLike {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "comment_id")
private Comment comment;

private LocalDateTime createDate;
}
2 changes: 0 additions & 2 deletions src/main/java/com/example/be/domain/Post.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ public class Post {

private String content;

private boolean isDone = false;

private LocalDateTime createDate;


Expand Down
22 changes: 22 additions & 0 deletions src/main/java/com/example/be/repository/CommentLikeRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.example.be.repository;

import com.example.be.domain.Comment;
import com.example.be.domain.CommentLike;
import com.example.be.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.Optional;

public interface CommentLikeRepository extends JpaRepository<CommentLike, Long> {

Optional<CommentLike> findByUserAndComment(User user, Comment comment);

boolean existsByUserAndComment(User user, Comment comment);

long countByComment(Comment comment);

@Query("SELECT COUNT(cl) FROM CommentLike cl WHERE cl.comment.id = :commentId")
long countByCommentId(@Param("commentId") Long commentId);
}
3 changes: 0 additions & 3 deletions src/main/java/com/example/be/repository/PostRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,8 @@
import java.util.Optional;

public interface PostRepository extends JpaRepository<Post, Long> {
// PostRepository에 추가
@Query("SELECT p FROM Post p LEFT JOIN FETCH p.comments ORDER BY p.createDate DESC")
Page<Post> findAllByOrderByCreateDateDesc(Pageable pageable);

// ID로 게시글 조회 (댓글 포함)
@EntityGraph(attributePaths = {"comments", "comments.user", "user"})
Optional<Post> findById(Long id);
}
94 changes: 94 additions & 0 deletions src/main/java/com/example/be/service/CommentLikeServiceImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.example.be.service;

import com.example.be.apiPayload.code.status.ErrorStatus;
import com.example.be.apiPayload.exception.handler.UserHandler;
import com.example.be.domain.Comment;
import com.example.be.domain.CommentLike;
import com.example.be.domain.User;
import com.example.be.repository.CommentLikeRepository;
import com.example.be.repository.CommentRepository;
import com.example.be.repository.UserRepository;
import com.example.be.web.dto.CommentDTO;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Optional;
import java.util.UUID;

@Service
@RequiredArgsConstructor
public class CommentLikeServiceImpl {
private final JwtUtilServiceImpl jwtUtilService;
private final UserRepository userRepository;
private final CommentRepository commentRepository;
private final CommentLikeRepository commentLikeRepository;

private User getUserFromRequest(HttpServletRequest request) {
try {
String accessToken = jwtUtilService.extractTokenFromCookie(request, "accessToken");
if (accessToken != null) {
String userId = jwtUtilService.getUserIdFromToken(accessToken);
return userRepository.findByUserId(UUID.fromString(userId)).orElse(null);
}
} catch (Exception e) {
throw new UserHandler(ErrorStatus._NOT_FOUND_COOKIE);
}
return null;
}

@Transactional
public CommentDTO.CommentLikeResponseDTO toggleCommentLike(Long commentId, HttpServletRequest request) {

User user= getUserFromRequest(request);

// 댓글 정보 가져오기
Comment comment = commentRepository.findById(commentId)
.orElseThrow(() -> new UserHandler(ErrorStatus._NOT_FOUND_COMMENT));

// 이미 좋아요를 눌렀는지 확인
Optional<CommentLike> existingLike = commentLikeRepository.findByUserAndComment(user, comment);

boolean isLiked;
if (existingLike.isPresent()) {
// 좋아요가 이미 있으면 삭제 (좋아요 취소)
commentLikeRepository.delete(existingLike.get());
isLiked = false;
} else {
// 좋아요가 없으면 추가
CommentLike commentLike = CommentLike.builder()
.user(user)
.comment(comment)
.createDate(LocalDateTime.now())
.build();
commentLikeRepository.save(commentLike);
isLiked = true;
}

// 좋아요 수 조회
long likeCount = commentLikeRepository.countByComment(comment);

return CommentDTO.CommentLikeResponseDTO.builder()
.commentId(commentId)
.liked(isLiked)
.likeCount(likeCount)
.build();
}

// 특정 댓글에 대한 사용자의 좋아요 여부 확인
public boolean isCommentLikedByUser(Comment comment, User user) {
return commentLikeRepository.existsByUserAndComment(user, comment);
}

// 특정 댓글의 좋아요 수 조회
public long getCommentLikeCount(Comment comment) {
return commentLikeRepository.countByComment(comment);
}

// 특정 댓글 ID의 좋아요 수 조회
public long getCommentLikeCount(Long commentId) {
return commentLikeRepository.countByCommentId(commentId);
}
}
22 changes: 14 additions & 8 deletions src/main/java/com/example/be/service/CommentServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,22 @@ public class CommentServiceImpl {
private final PostRepository postRepository;
private final CommentRepository commentRepository;

@Transactional
public CommonDTO.IsSuccessDTO createComment(CommentDTO.CommentRequestDTO requestDTO, HttpServletRequest request) {
String accessToken = jwtUtilService.extractTokenFromCookie(request, "accessToken");
if (accessToken == null) {
throw new UserHandler(ErrorStatus._NOT_FOUND_USER);
private User getUserFromRequest(HttpServletRequest request) {
try {
String accessToken = jwtUtilService.extractTokenFromCookie(request, "accessToken");
if (accessToken != null) {
String userId = jwtUtilService.getUserIdFromToken(accessToken);
return userRepository.findByUserId(UUID.fromString(userId)).orElse(null);
}
} catch (Exception e) {
throw new UserHandler(ErrorStatus._NOT_FOUND_COOKIE);
}
return null;
}

String userId = jwtUtilService.getUserIdFromToken(accessToken);
User user = userRepository.findByUserId(UUID.fromString(userId))
.orElseThrow(() -> new UserHandler(ErrorStatus._NOT_FOUND_USER));
@Transactional
public CommonDTO.IsSuccessDTO createComment(CommentDTO.CommentRequestDTO requestDTO, HttpServletRequest request) {
User user= getUserFromRequest(request);

Post post = postRepository.findById(requestDTO.getPostId())
.orElseThrow(() -> new UserHandler(ErrorStatus._NOT_FOUND_POST));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ public String getUserIdFromToken(String token) {
.parseSignedClaims(token)
.getPayload()
.get("userId", String.class);
log.info("유저 id를 반환합니다.");
return userId;
} catch (JwtException | IllegalArgumentException e) {
// 토큰이 유효하지 않은 경우
Expand Down
28 changes: 15 additions & 13 deletions src/main/java/com/example/be/service/PostLikeServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,32 +27,34 @@ public class PostLikeServiceImpl {
private final PostRepository postRepository;
private final PostLikeRepository postLikeRepository;

@Transactional
public PostDTO.PostLikeResponseDTO togglePostLike(Long postId, HttpServletRequest request) {
// 토큰에서 사용자 정보 가져오기
String accessToken = jwtUtilService.extractTokenFromCookie(request, "accessToken");
if (accessToken == null) {
throw new UserHandler(ErrorStatus._NOT_FOUND_USER);
private User getUserFromRequest(HttpServletRequest request) {
try {
String accessToken = jwtUtilService.extractTokenFromCookie(request, "accessToken");
if (accessToken != null) {
String userId = jwtUtilService.getUserIdFromToken(accessToken);
return userRepository.findByUserId(UUID.fromString(userId)).orElse(null);
}
} catch (Exception e) {
throw new UserHandler(ErrorStatus._NOT_FOUND_COOKIE);
}
return null;
}

String userId = jwtUtilService.getUserIdFromToken(accessToken);
User user = userRepository.findByUserId(UUID.fromString(userId))
.orElseThrow(() -> new UserHandler(ErrorStatus._NOT_FOUND_USER));

// 게시글 정보 가져오기
@Transactional
public PostDTO.PostLikeResponseDTO togglePostLike(Long postId, HttpServletRequest request) {

User user = getUserFromRequest(request);
Post post = postRepository.findById(postId)
.orElseThrow(() -> new UserHandler(ErrorStatus._NOT_FOUND_POST));

// 이미 좋아요를 눌렀는지 확인
Optional<PostLike> existingLike = postLikeRepository.findByUserAndPost(user, post);

boolean isLiked;
if (existingLike.isPresent()) {
// 좋아요가 이미 있으면 삭제 (좋아요 취소)
postLikeRepository.delete(existingLike.get());
isLiked = false;
} else {
// 좋아요가 없으면 추가
PostLike postLike = PostLike.builder()
.user(user)
.post(post)
Expand Down
Loading