public class Heart {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "heart_id")
private Long id;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "member_id")
private Member member;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "review_id")
private Review review;
private boolean liked;
//== 생성 메서드 ==//
public static Heart createHeart(Member member, Review review, Boolean liked) {
Heart heart = new Heart();
heart.setMember(member);
heart.setReview(review);
heart.setLiked(false);
return heart;
}
public void like() {
if (!this.liked){
this.liked = true;
this.review.addHeart(this);
} else {
this.unlike();
}
}
public void unlike() {
if (this.liked) {
this.liked = false;
this.review.removeHeart(this);
}
}
@Builder
public Heart(Member member, Review review, boolean liked) {
this.member = member;
this.review = review;
this.liked = liked;
}
회원과 리뷰엔티티에 다 대 일 관계를 맺고, 생성 메서드와 좋아요로직을 만들어 두었다.
public class HeartRepository {
@PersistenceContext
private final EntityManager em;
public void save(Heart heart) {
em.persist(heart);
}
public Heart findOne(Long id) {
return em.find(Heart.class, id);
}
public Heart findLiked(Member member, Review review) {
return em.createQuery("select h from Heart h where h.member = :member and h.review = :review", Heart.class)
.setParameter("member", member)
.setParameter("review", review)
.getResultList()
.stream()
.findFirst()
.orElse(null);
}
public void delete(Heart heart) {
em.remove(heart);
}
save와 findOne, findLiked, delete를 만들어 줌
findLiked는 리뷰정보와 회원정보를 받아 이미 DB에 값이 있을 경우 반환 해 주고 없을 경우 null을 반환하게 만들어 주었다.
public int toggleHeart(Long memberId, Long reviewId) {
//회원과 리뷰를 DB에서 찾아서 Heart객체가 존재하는지 체크(존재한다 == true)
Member member = memberRepository.findOne(memberId);
Review review = reviewRepository.findOne(reviewId);
Heart heart = heartRepository.findLiked(member, review);
if (heart == null) {
heart = Heart.createHeart(member, review, false);
heart.like();
}
else {
heart.unlike();
heartRepository.delete(heart);
}
heartRepository.save(heart);
return review.getLikeCount();
}
이미 좋아요를 누른 회원인지 처음 누르 회원인지 판별하기 위해 좋아요를 처음 누르면 Heart객체를 생성하였고, 회원아이디와 리뷰아이디를 받아와 findLiked해 주었을 때 값이 없을 경우 createHeart로 객체를 생성하여 넣어주고 like메서드 실행. true로 있을 경우 unlike 메서드 실행 후 삭제. 값을 save로 반영하여 반환.
@Test
public void 좋아요기능() throws Exception {
//given
Member member = Member.builder()
.profile_nickname("Kim")
.build();
em.persist(member);
Review review = Review.builder()
.likeCount(2)
.title("맛있음")
.build();
em.persist(review);
Heart heart = Heart.builder()
.member(member)
.review(review)
.liked(true)
.build();
em.persist(heart);
//when
int heartCount = heartService.toggleHeart(member.getId(), review.getId());
//Then
assertThat(heartCount).isEqualTo(1);
}
테스트코드는 아직 미숙한 점이 많은 것 같다. 좋아요의 개수가 2개인 리뷰에 이미 좋아요를 누른 회원이 다시 누를 경우를 생각하여 테스트 코드를 작성하였다.
예상값은 1이고 결과도 1이 나왔다.