안녕하세요 이번 시간에는 게시물 좋아요 기능을 만들어 보도록 하겠습니다.

수정할 파일 : PostController, PostService, PostEntity, UserEntity

생성할 파일 : PostLikeEntity, PostLikeRepository

- PostController

   @PostMapping("/post/{id}/like")
    @PreAuthorize("isAuthenticated()")
    public SuccessResponse<String> postLike(@PathVariable(name = "id") Long postId, Principal principal) {
        postService.postLike(postId, principal.getName());
        return SuccessResponse.success(null);
    }

좋아요 할 게시물의 id와 현재 로그인 중인 유저의 email을 Service에 넘겨줍니다.

 

 

- PostService

   public void postLike(Long postId, String email) {
        Post post = getPostInService(postId);
        User user = getUserInService(email);
        Optional<PostLike> byPostAndUser = postLikeRepository.findByPostAndUser(post, user);

        byPostAndUser.ifPresentOrElse(
		// 좋아요 있을경우 삭제
                postLike -> {
                    postLikeRepository.delete(postLike);
                    post.discountLike(postLike);
                },
                // 좋아요가 없을 경우 좋아요 추가
                () -> {
                    PostLike postLike = PostLike.builder().build();

                    postLike.mappingPost(post);
                    postLike.mappingUser(user);
                    post.updateLikeCount();

                    postLikeRepository.save(postLike);
                }
        );
    }

ifPresentOrElse 구문은 게시물과 유저로 찾아 좋아요을 했을 경우와 하지 않았을 경우를 나눠 로직을 작성할수 있습니다.

좋아요가 있을경우 테이블에서 삭제를 한 후 Post에서 LikeCount를 하나 줄여줍니다.

좋아요가 없다면 user와 post를 매핑해 준 후 LikeCount를 업데이트 해줍니다.

 

- PostEntity

@OneToMany(fetch = LAZY, mappedBy = "post", cascade = CascadeType.REMOVE)
    private List<PostLike> postLikeList = new ArrayList<>();
    
    
public void mappingPostLike(PostLike postLike) {
        this.postLikeList.add(postLike);
    }

    public void updateLikeCount() {
        this.likeCount = (long) this.postLikeList.size();
    }

    public void discountLike(PostLike postLike) {
        this.postLikeList.remove(postLike);

    }

 

- UserEntity

 @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.REMOVE)
    private List<PostLike> postLikeList = new ArrayList<>();
    
  public void mappingPostLike(PostLike postLike) {
        this.postLikeList.add(postLike);
    }

 

- PostLikeEntity

@Entity
@Getter
@Builder
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class PostLike {

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

    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "user_id", foreignKey = @ForeignKey(name = "FK_PostLike_User"))
    private User user;

    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "post_id", foreignKey = @ForeignKey(name = "FK_PostLike_Post"))
    private Post post;

    public static boolean isVotedPost(Optional<PostLike> optionalPostLike) {
        return optionalPostLike.isPresent();
    }

    public void mappingUser(User user) {
        this.user = user;
        user.mappingPostLike(this);
    }

    public void mappingPost(Post post) {
        this.post = post;
        post.mappingPostLike(this);
    }

}

Post와 User를 직접적으로 N : M 로 매핑하지 않고 중간 테이블을 만들어 1 : N - M : 1 로 매핑한 이유는 나중에 좋아요을 한 날짜나 다른 정보들이 필요한 경우 이렇게 중간 테이블을 만들어 놓는다면 중간 테이블에 관련된 데이터를 추가 하면 되지만 직접 적으로 연결 할 경우 등록하기 어렵기 때문입니다.

 

- PostLikeRepository

@Repository
public interface PostLikeRepository extends JpaRepository<PostLike, Long> {
    Optional<PostLike> findByPostAndUser(Post post, User user);
}

게시물과 유저로 좋아요를 찾습니다.

+ Recent posts