Skip to content

Commit

Permalink
feat(like) : 좋아요 기능 개발 (#37)
Browse files Browse the repository at this point in the history
* feat(like) : 좋아요 도메인

* feat(like) : 좋아요 생성 Api

* feat(like) : 좋아요 삭제 Api

* refactor(like) : QnA 삭제 시 좋아요도 같이 삭제

* chore(server) : .gitignore 수정

* feat(like) : 좋아요 여부 Api

* refactor(like) : 함수명 변경
  • Loading branch information
Woongbin06 authored Jan 7, 2024
1 parent fe6c020 commit c743ed1
Show file tree
Hide file tree
Showing 13 changed files with 297 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
!**/src/main/generated/
/src/main/generated/

### STS ###
.apt_generated
Expand Down
42 changes: 42 additions & 0 deletions src/main/java/com/sickgyun/server/like/domain/Like.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.sickgyun.server.like.domain;

import com.sickgyun.server.qna.QnA;
import com.sickgyun.server.user.domain.User;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "like_tbl")
public class Like {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "like_id")
private Long id;

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

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "qna_id")
private QnA qnA;

public Like(User user, QnA qnA) {
this.user = user;
this.qnA = qnA;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.sickgyun.server.like.domain.repository;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;

import com.sickgyun.server.like.domain.Like;
import com.sickgyun.server.like.exception.LikeNotFoundException;
import com.sickgyun.server.qna.QnA;
import com.sickgyun.server.user.domain.User;

public interface LikeRepository extends JpaRepository<Like, Long> {
boolean existsByQnAAndUser(QnA qnA, User user);

Optional<Like> findByQnAAndUser(QnA qnA, User user);

void deleteByQnA(QnA qnA);

default Like getLike(QnA qnA, User user) {
return findByQnAAndUser(qnA, user)
.orElseThrow(LikeNotFoundException::new);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.sickgyun.server.like.exception;

import org.springframework.http.HttpStatus;

import com.sickgyun.server.common.exception.SickgyunException;

public class AlreadyLikeException extends SickgyunException {

public AlreadyLikeException() {
super(HttpStatus.BAD_REQUEST, "이미 좋아요한 QnA입니다.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.sickgyun.server.like.exception;

import org.springframework.http.HttpStatus;

import com.sickgyun.server.common.exception.SickgyunException;

public class LikeNotFoundException extends SickgyunException {

public LikeNotFoundException() {
super(HttpStatus.NOT_FOUND, "좋아요를 찾을 수 없습니다.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.sickgyun.server.like.presentation;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
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.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.sickgyun.server.like.service.CommandLikeService;
import com.sickgyun.server.like.service.QueryLikeService;
import com.sickgyun.server.user.domain.User;
import com.sickgyun.server.user.service.UserTempService;

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/likes")
public class LikeController {

private final CommandLikeService commandLikeService;
private final QueryLikeService queryLikeService;
private final UserTempService userTempService;

@ResponseStatus(HttpStatus.CREATED)
@PostMapping("/{qna-id}")
public void createLike(@PathVariable(name = "qna-id") Long qnAId) {
User user = userTempService.getUserId1();
commandLikeService.create(qnAId, user);
}

@ResponseStatus(HttpStatus.NO_CONTENT)
@DeleteMapping("/{qna-id}")
public void deleteLike(@PathVariable(name = "qna-id") Long qnAId) {
User user = userTempService.getUserId1();
commandLikeService.delete(qnAId, user);
}

@GetMapping("/{qna-id}")
public boolean checkLiked(@PathVariable(name = "qna-id") Long qnAId) {
User user = userTempService.getUserId1();
return queryLikeService.checkLike(qnAId, user);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.sickgyun.server.like.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sickgyun.server.like.domain.Like;
import com.sickgyun.server.like.service.implememtation.LikeCreator;
import com.sickgyun.server.like.service.implememtation.LikeDeleter;
import com.sickgyun.server.like.service.implememtation.LikeReader;
import com.sickgyun.server.like.service.implememtation.LikeValidator;
import com.sickgyun.server.qna.QnA;
import com.sickgyun.server.qna.service.implementation.QnAReader;
import com.sickgyun.server.user.domain.User;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
@Transactional
public class CommandLikeService {

private final LikeCreator likeCreator;
private final LikeReader likeReader;
private final LikeDeleter likeDeleter;
private final LikeValidator likeValidator;
private final QnAReader qnAReader;

public void create(Long qnAId, User user) {
QnA qnA = qnAReader.read(qnAId);
likeValidator.shouldNotExistLike(qnA, user);
likeCreator.create(new Like(user, qnA));
}

public void delete(Long qnAId, User user) {
QnA qnA = qnAReader.read(qnAId);
Like like = likeReader.read(qnA, user);
likeDeleter.delete(like);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.sickgyun.server.like.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sickgyun.server.like.service.implememtation.LikeValidator;
import com.sickgyun.server.qna.QnA;
import com.sickgyun.server.qna.service.implementation.QnAReader;
import com.sickgyun.server.user.domain.User;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class QueryLikeService {

private final QnAReader qnAReader;
private final LikeValidator likeValidator;

public boolean checkLike(Long qnAId, User user) {
QnA qnA = qnAReader.read(qnAId);
return likeValidator.checkLiked(qnA, user);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.sickgyun.server.like.service.implememtation;

import org.springframework.stereotype.Service;

import com.sickgyun.server.like.domain.Like;
import com.sickgyun.server.like.domain.repository.LikeRepository;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class LikeCreator {

private final LikeRepository likeRepository;

public void create(Like like) {
likeRepository.save(like);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.sickgyun.server.like.service.implememtation;

import org.springframework.stereotype.Service;

import com.sickgyun.server.like.domain.Like;
import com.sickgyun.server.like.domain.repository.LikeRepository;
import com.sickgyun.server.qna.QnA;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class LikeDeleter {

private final LikeRepository likeRepository;

public void delete(Like like) {
likeRepository.delete(like);
}

public void deleteByQnA(QnA qnA) {
likeRepository.deleteByQnA(qnA);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.sickgyun.server.like.service.implememtation;

import org.springframework.stereotype.Service;

import com.sickgyun.server.like.domain.Like;
import com.sickgyun.server.like.domain.repository.LikeRepository;
import com.sickgyun.server.qna.QnA;
import com.sickgyun.server.user.domain.User;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class LikeReader {

private final LikeRepository likeRepository;

public Like read(QnA qnA, User user) {
return likeRepository.getLike(qnA, user);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.sickgyun.server.like.service.implememtation;

import org.springframework.stereotype.Service;

import com.sickgyun.server.like.domain.repository.LikeRepository;
import com.sickgyun.server.like.exception.AlreadyLikeException;
import com.sickgyun.server.qna.QnA;
import com.sickgyun.server.user.domain.User;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class LikeValidator {

private final LikeRepository likeRepository;

public void shouldNotExistLike(QnA qnA, User user) {
boolean isExist = likeRepository.existsByQnAAndUser(qnA, user);

if (isExist) {
throw new AlreadyLikeException();
}
}

public boolean checkLiked(QnA qnA, User user) {
return likeRepository.existsByQnAAndUser(qnA, user);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import com.sickgyun.server.comment.service.implementation.CommentDeleter;
import com.sickgyun.server.like.service.implememtation.LikeDeleter;
import com.sickgyun.server.qna.QnA;
import com.sickgyun.server.qna.service.implementation.QnACreator;
import com.sickgyun.server.qna.service.implementation.QnADeleter;
Expand All @@ -23,6 +23,7 @@ public class CommandQnAService {
private final QnAReader qnAReader;
private final QnADeleter qnADeleter;
private final CommentDeleter commentDeleter;
private final LikeDeleter likeDeleter;

public void createQnA(QnA qnA) {
qnACreator.create(qnA);
Expand All @@ -37,5 +38,6 @@ public void deleteQnA(Long qnAId) {
QnA qnA = qnAReader.read(qnAId);
qnADeleter.delete(qnA);
commentDeleter.deleteByQnA(qnA);
likeDeleter.deleteByQnA(qnA);
}
}

0 comments on commit c743ed1

Please sign in to comment.