안녕하세요 이번 시간에는 게시물 좋아요 기능을 만들어 보도록 하겠습니다.
수정할 파일 : 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);
}
게시물과 유저로 좋아요를 찾습니다.
'스프링 부트' 카테고리의 다른 글
스프링부트 게시판 API 만들기 - 리팩토링 (if else 구문을 strategy 패턴으로 바꾸기) (0) | 2021.05.08 |
---|---|
스프링부트 게시판 API 만들기 - 끝 (AWS S3에 이미지 업로드 하기) (0) | 2021.05.05 |
스프링부트 게시판 API 만들기 - 12 (게시물 검색기능 및 QueryDSL) - 2 (0) | 2021.05.03 |
스프링부트 게시판 API 만들기 - 11 (게시물 검색기능 및 QueryDSL) - 1 (0) | 2021.05.01 |
스프링부트 게시판 API 만들기 - 10 (댓글 기능 만들기 및 쿼리 최적화2) (0) | 2021.04.30 |