모델을 만들었으니 Repository, Service, Controller도 만들어주자
LikesRepository
package com.cos.photogramstart.domain.likes;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
public interface LikesRepository extends JpaRepository<Likes, Integer> {
@Modifying
@Query(value = "INSERT INTO likes(imageId, userId, createDate) VALUES(:imageId, :principalId, now())", nativeQuery = true)
int mLikes(int imageId, int principalId);
@Modifying
@Query(value = "DELETE FROM likes WHERE imageId = :imageId AND userId = :principalId", nativeQuery = true)
int mUnLikes(int imageId, int principalId);
}
LikesService
package com.cos.photogramstart.domain.likes;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@RequiredArgsConstructor
@Service
public class LikesService {
private final LikesRepository likesRepository;
@Transactional
public void 좋아요(int imageId, int principalId) {
likesRepository.mLikes(imageId, principalId);
}
@Transactional
public void 좋아요취소(int imageId, int principalId) {
likesRepository.mUnLikes(imageId, principalId);
}
}
ImageApiController
package com.cos.photogramstart.web.api;
import com.cos.photogramstart.config.PrincipalDetails;
import com.cos.photogramstart.domain.Image.Image;
import com.cos.photogramstart.domain.likes.LikesService;
import com.cos.photogramstart.service.ImageService;
import com.cos.photogramstart.web.dto.CMRespDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
@RestController
@RequiredArgsConstructor
public class ImageApiController {
private final ImageService imageService;
private final LikesService likesService;
@GetMapping("/api/image")
public ResponseEntity<?> imageStory(@AuthenticationPrincipal PrincipalDetails principalDetails,
@PageableDefault(size = 3)
Pageable pageable) {
Page<Image> images = imageService.이미지스토리(principalDetails.getUser().getId(), pageable);
return new ResponseEntity<>(new CMRespDTO<>(1, "성공", images), HttpStatus.OK);
}
@PostMapping("/api/image/{imageId}/likes")
public ResponseEntity<?> likes(@PathVariable int imageId,
@AuthenticationPrincipal PrincipalDetails principalDetails) {
likesService.좋아요(imageId, principalDetails.getUser().getId());
return new ResponseEntity<>(new CMRespDTO<>(1, "좋아요성공", null), HttpStatus.CREATED);
}
@DeleteMapping("/api/image/{imageId}/likes")
public ResponseEntity<?> unLikes(@PathVariable int imageId,
@AuthenticationPrincipal PrincipalDetails principalDetails) {
likesService.좋아요취소(imageId, principalDetails.getUser().getId());
return new ResponseEntity<>(new CMRespDTO<>(1, "좋아요취소성공", null), HttpStatus.OK);
}
}
-> 해당 컨트롤러는 Image에 딸려갈 것이기 때문에 주소경로도 image이고, Controller도 ImageApiController에 만들어주었다.
-> LikesService를 DI하고, '좋아요'와 '좋아요취소' 메서드를 호출한다. 이때, Image의 Id와 User의 Id를 받아주어야 한다.
package com.cos.photogramstart.domain.likes;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@RequiredArgsConstructor
@Service
public class LikesService {
private final LikesRepository likesRepository;
@Transactional
public void 좋아요(int imageId, int principalId) {
likesRepository.mLikes(imageId, principalId);
}
@Transactional
public void 좋아요취소(int imageId, int principalId) {
likesRepository.mUnLikes(imageId, principalId);
}
}
-> Service에서도 똑같이 받아준다.
package com.cos.photogramstart.domain.likes;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
public interface LikesRepository extends JpaRepository<Likes, Integer> {
@Modifying
@Query(value = "INSERT INTO likes(imageId, userId, createDate) VALUES(:imageId, :principalId, now())", nativeQuery = true)
int mLikes(int imageId, int principalId);
@Modifying
@Query(value = "DELETE FROM likes WHERE imageId = :imageId AND userId = :principalId", nativeQuery = true)
int mUnLikes(int imageId, int principalId);
}
-> Repository에 '네이티브 쿼리'를 작성한다.
package com.cos.photogramstart.web.api;
import com.cos.photogramstart.config.PrincipalDetails;
import com.cos.photogramstart.domain.Image.Image;
import com.cos.photogramstart.domain.likes.LikesService;
import com.cos.photogramstart.service.ImageService;
import com.cos.photogramstart.web.dto.CMRespDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
@RestController
@RequiredArgsConstructor
public class ImageApiController {
private final ImageService imageService;
private final LikesService likesService;
@GetMapping("/api/image")
public ResponseEntity<?> imageStory(@AuthenticationPrincipal PrincipalDetails principalDetails,
@PageableDefault(size = 3)
Pageable pageable) {
Page<Image> images = imageService.이미지스토리(principalDetails.getUser().getId(), pageable);
return new ResponseEntity<>(new CMRespDTO<>(1, "성공", images), HttpStatus.OK);
}
@PostMapping("/api/image/{imageId}/likes")
public ResponseEntity<?> likes(@PathVariable int imageId,
@AuthenticationPrincipal PrincipalDetails principalDetails) {
likesService.좋아요(imageId, principalDetails.getUser().getId());
return new ResponseEntity<>(new CMRespDTO<>(1, "좋아요성공", null), HttpStatus.CREATED);
}
@DeleteMapping("/api/image/{imageId}/likes")
public ResponseEntity<?> unLikes(@PathVariable int imageId,
@AuthenticationPrincipal PrincipalDetails principalDetails) {
likesService.좋아요취소(imageId, principalDetails.getUser().getId());
return new ResponseEntity<>(new CMRespDTO<>(1, "좋아요취소성공", null), HttpStatus.OK);
}
}
-> 좋아요를 Controller로 돌아가서 응답성공시에 리턴할 값을 넣어주면 된다.
다 만들었으니 POSTMAN으로 테스트해보자
package com.cos.photogramstart.domain.Image;
import com.cos.photogramstart.domain.user.User;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.time.LocalDateTime;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Image { //N:1
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String caption; //해당 Image를 설명하는 영역
private String postImageUrl; //Image을 전송받아서 그 사진을 서버의 특정 폴더에 저장 - DB에 그 저장된 경로를 INSERT
@JsonIgnoreProperties({"images"})
@JoinColumn(name = "userId") // 1:1
@ManyToOne(fetch = FetchType.EAGER)
private User user; //1명의 User는 여러개의 Image를 만들어낼수 있다. - Image를 누가 올렸는지 알기위해 받은 USerObject
//이미지 좋아요 기능 (추후에 업데이트)
//이미지 좋아요 카운팅 (추후에 업데이트)
//댓글 기능 (추후에 업데이트)
private LocalDateTime createDate; //모든 DB에는 시간정보가 필요하다 - 데이터가 입력된 시간
@PrePersist
public void createDate() {
this.createDate = LocalDateTime.now();
}
/**오브젝트를 콘솔에 출력할 때 문제가 될 수 있어서 User부분을 출력되지 않게 함
* @Override
public String toString() {
return "Image{" +
"id=" + id +
", caption='" + caption + '\'' +
", postImageUrl='" + postImageUrl + '\'' +
", createDate=" + createDate +
'}';
}
**/
}
package com.cos.photogramstart.domain.likes;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
public interface LikesRepository extends JpaRepository<Likes, Integer> {
@Modifying
@Query(value = "INSERT INTO likes(imageId, userId, createDate) VALUES(:imageId, :principalId, now())", nativeQuery = true)
int mLikes(int imageId, int principalId);
@Modifying
@Query(value = "DELETE FROM likes WHERE imageId = :imageId AND userId = :principalId", nativeQuery = true)
int mUnLikes(int imageId, int principalId);
}
-> DELETE에는 당연히 넣을 필요가 없다. 다시한번 '좋아요' 테스트를 진행해보자.
'메타코딩 SNS프로젝트' 카테고리의 다른 글
48. chapter8. 좋아요 구현 - 좋아요 카운트 View 렌더링 (0) | 2022.07.08 |
---|---|
47. chapter 8. 좋아요 구현 - 좋아요 View 렌더링, 무한참조 해결 (0) | 2022.07.08 |
45. Chapter8. 좋아요 구현 - Likes 모델링하기 (0) | 2022.07.07 |
44. 스토리 페이지 - 스크롤 페이징 구현하기 (0) | 2022.07.07 |
43. 스토리 페이지 - 페이징하기 (0) | 2022.07.07 |