Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat : 게시글 좋아요, 좋아요 해제 구현 및 테스트코드 작성 #31

Merged
merged 5 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Expand Up @@ -22,6 +22,7 @@ public enum ExceptionCode {
INCORRECT_TOKEN(UNAUTHORIZED, "올바르지 않는 토큰입니다."),
ALREADY_REGISTERED_EMAIL(CONFLICT, "이미 등록된 이메일입니다."),
NOT_FOUND_POST(NOT_FOUND, "게시물을 찾을 수 없습니다."),
ALREADY_EXIST_POSTLIKE(CONFLICT, "이미 좋아요를 누른 게시물입니다."),
NOT_CORRECT_USER(UNAUTHORIZED, "작성자가 일치하지 않습니다."),
PUBLIC_KEY_GENERATION_FAILED(INTERNAL_SERVER_ERROR ,"공개 키 생성에 실패했습니다.");
;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package thisisus.school.post.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import thisisus.school.auth.config.AuthenticatedMemberId;
import thisisus.school.common.response.SuccessResonse;
import thisisus.school.post.service.PostLikeService;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/like")
changhyun-jang marked this conversation as resolved.
Show resolved Hide resolved
public class PostLikeController {

private final PostLikeService postLikeService;

@PostMapping("/{postId}")
public SuccessResonse insertLike(@PathVariable("postId") final Long postId,
@AuthenticatedMemberId final Long memberId) {
postLikeService.insertLike(postId, memberId);
return SuccessResonse.of();
}
}
73 changes: 40 additions & 33 deletions BE/school/src/main/java/thisisus/school/post/domain/Post.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.ColumnDefault;
import thisisus.school.common.BaseTimeEntity;
import thisisus.school.member.domain.Member;
import thisisus.school.post.exception.NotCorrectUserException;
Expand All @@ -26,47 +27,53 @@
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Post extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "post_id")
private Long id;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "post_id")
private Long id;

@Column
private String title;
@Column
private String title;

@Column
private String content;
@Column
private String content;

@Column
@Enumerated(EnumType.STRING)
private PostCategory category;
@Column
@Enumerated(EnumType.STRING)
private PostCategory category;

@Column
private int likeCount;
@Column
@ColumnDefault("0")
private Integer likeCount;

@Column
private int viewCount;
@Column
@ColumnDefault("0")
private Integer viewCount;

@Column
private boolean isDelete;
@Column
private boolean isDelete;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;

public void delete() {
this.isDelete = true;
}
public void delete() {
this.isDelete = true;
}

public void update(String title, String content, PostCategory category) {
this.title = title;
this.content = content;
this.category = category;
}
public void update(String title, String content, PostCategory category) {
this.title = title;
this.content = content;
this.category = category;
}

public void checkWriter(Post post, Long memberId) {
if (post.getMember().getId() != memberId) {
throw new NotCorrectUserException();
}
}
public void checkWriter(Post post, Long memberId) {
if (post.getMember().getId() != memberId) {
throw new NotCorrectUserException();
}
}

public void increaseLikeCount() {
this.likeCount = getLikeCount() + 1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package thisisus.school.post.exception;

import thisisus.school.common.exception.CustomException;
import thisisus.school.common.exception.ExceptionCode;

public class AlreadyExistPostLikeException extends CustomException {
public AlreadyExistPostLikeException() {
super(ExceptionCode.ALREADY_EXIST_POSTLIKE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package thisisus.school.post.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import thisisus.school.member.domain.Member;
import thisisus.school.post.domain.Post;
import thisisus.school.post.domain.PostLike;

import java.util.Optional;

@Repository
public interface PostLikeRepository extends JpaRepository<PostLike, Long> {
boolean existsByMemberAndPost(Member member, Post post);
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package thisisus.school.post.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Lock;
import thisisus.school.post.domain.Post;

import javax.persistence.LockModeType;
import java.util.List;
import java.util.Optional;

public interface PostRepository extends JpaRepository<Post, Long> {
List<Post> findAllByMemberId(Long memberId);

@Lock(LockModeType.PESSIMISTIC_WRITE)
Optional<Post> findWithLockById(Long id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package thisisus.school.post.service;

public interface PostLikeService {
void insertLike(Long postId, Long memberId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package thisisus.school.post.service;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import thisisus.school.member.domain.Member;
import thisisus.school.member.exception.NotFoundMemberException;
import thisisus.school.member.repository.MemberRepository;
import thisisus.school.post.domain.Post;
import thisisus.school.post.domain.PostLike;
import thisisus.school.post.exception.AlreadyExistPostLikeException;
import thisisus.school.post.exception.NotFoundPostException;
import thisisus.school.post.repository.PostLikeRepository;
import thisisus.school.post.repository.PostRepository;

@Service
@RequiredArgsConstructor
public class PostLikeServiceImpl implements PostLikeService {
private final PostLikeRepository postLikeRepository;
private final PostRepository postRepository;
private final MemberRepository memberRepository;

@Override
@Transactional
public synchronized void insertLike(Long postId, Long memberId) {
changhyun-jang marked this conversation as resolved.
Show resolved Hide resolved
Member member = memberRepository.findById(memberId)
.orElseThrow(NotFoundMemberException::new);
Post post = postRepository.findWithLockById(postId)
.orElseThrow(NotFoundPostException::new);
if (postLikeRepository.existsByMemberAndPost(member, post)) {
throw new AlreadyExistPostLikeException();
}
post.increaseLikeCount();
postRepository.save(post);
changhyun-jang marked this conversation as resolved.
Show resolved Hide resolved

PostLike postLike = PostLike.builder()
.post(post)
.member(member)
.build();

postLikeRepository.save(postLike);
}
}