목차📕
- 게시물 작성 기능 구현
- 게시물 조회 기능 구현
- 게시물 수정 기능 구현
- 게시물 삭제 기능 구현
- pull 받은 후 구현
TimeEntity
package com.sparta.newsfeed.entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.time.LocalDateTime;
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class TimeEntity {
@CreatedDate
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime modifiedDate;
}
@MappedSuperClass
JPA Entity 클래스들이 BaseTimeEntity를 상속할 경우 이 클래스의 변수인 createdDate와 modifiedDate도 칼럼으로 인식하게한다.
@EntityListners(AuditingEntityListener.class)
BaseTimeEntity 클래스에 Auditing 기능을 포함시킨다.
@CreatedDate
Entity가 생성되면, createdDate에 저장 시간이 자동으로 저장된다.
@LastModifiedDate
조회한 Entity의 값을 변경할 때 시간이 자동 저장된다.
이렇게 만들어준 BaseTimeEntity를 Entity인 Posts에 상속해주고, JPA Auditing을 활성화 할 수 있도록 Application 클래스에 활성화 어노테이션을 추가해주면, 자동으로 데이터베이스에 생성시간과 수정시간을 포함하여 저장할 수 있다.
entity > Post
package com.sparta.newsfeed.entity;
import com.sparta.newsfeed.dto.PostRequsetDto;
import com.sparta.newsfeed.dto.PostResponseDto;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Entity
@Getter
@NoArgsConstructor
@Table(name = "posts")
public class Post extends TimeEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@Column(nullable = false)
private String content;
public Post(PostRequsetDto requsetDto){
this.title = requsetDto.getTitle();
this.content = requsetDto.getContent();
}
}
controller > PostController
package com.sparta.newsfeed.controller;
import com.sparta.newsfeed.dto.PostRequsetDto;
import com.sparta.newsfeed.dto.PostResponseDto;
import com.sparta.newsfeed.service.PostService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/posts")
public class PostController {
private final PostService postService;
public PostController(PostService postService) {
this.postService = postService;
}
//게시물 생성
@PostMapping("/create")
public PostResponseDto createPost(@RequestBody PostRequsetDto requsetDto){
return postService.createPost(requsetDto);
}
}
dto > PostRequestDto
package com.sparta.newsfeed.dto;
import lombok.Getter;
@Getter
public class PostRequsetDto {
private String title;
private String content;
}
dto > PostResponseDto
package com.sparta.newsfeed.dto;
import com.sparta.newsfeed.entity.Post;
import lombok.Getter;
import lombok.Setter;
import org.springframework.cglib.core.Local;
import java.time.LocalDateTime;
@Getter
@Setter
public class PostResponseDto {
private Long id;
private String title;
private String content;
private LocalDateTime createdDate;
private LocalDateTime modifiedDate;
public PostResponseDto(Post post){
this.id = post.getId();
this.title = post.getTitle();
this.content= post.getContent();
this.createdDate = post.getCreatedDate();
this.modifiedDate = post.getModifiedDate();
}
}
service > PostService
package com.sparta.newsfeed.service;
import com.sparta.newsfeed.dto.PostRequsetDto;
import com.sparta.newsfeed.dto.PostResponseDto;
import com.sparta.newsfeed.entity.Post;
import com.sparta.newsfeed.repository.PostRepository;
import org.springframework.stereotype.Service;
@Service
public class PostService {
private final PostRepository postRepository;
public PostService(PostRepository postRepository) {
this.postRepository = postRepository;
}
//게시물 생성
public PostResponseDto createPost(PostRequsetDto requsetDto) {
Post post = new Post(requsetDto);
postRepository.save(post);
return new PostResponseDto(post);
}
}
repository > PostRepository
package com.sparta.newsfeed.repository;
import com.sparta.newsfeed.entity.Post;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PostRepository extends JpaRepository<Post, Long> {
}
@JsonInclude(JsonInclude.Include.NON_NULL) // -> JSON으로 받아올 때 null인 것들을 빼고 받아옴
//게시물 1건 조회
@GetMapping("/{postid}")
public PostResponseDto getOnePost(@PathVariable Long postid){
return postService.getOnePost(postid);
}
public PostResponseDto getOnePost(Long postid) {
Post post = postRepository.findById(postid).orElseThrow(() -> new IllegalArgumentException("존재하지 않는 id 입니다."));
return new PostResponseDto(post);
}
PostController
//게시물 전체 조회
@GetMapping
public List<PostResponseDto> getAllPost(){
return postService.getAllPost();
}
PostService
//게시물 전체 조회
public List<PostResponseDto> getAllPost() {
List<Post> postList = postRepository.findAll(Sort.by(Sort.Direction.DESC, "modifiedDate"));
List<PostResponseDto> responseDtoList = new ArrayList<>();
for(Post post : postList){
responseDtoList.add(new PostResponseDto(post));
}
return responseDtoList;
}
//게시물 수정
@PutMapping("/{postid}")
public PostResponseDto updatePost(@PathVariable Long postid, @RequestBody PostRequsetDto requsetDto){
return postService.updatePost(postid, requsetDto);
}
//게시물 수정
@Transactional
public PostResponseDto updatePost(Long postid, PostRequsetDto requsetDto) {
Post post = postRepository.findById(postid).orElseThrow(() -> new IllegalArgumentException("존재하지 않는 id 입니다."));
post.update(requsetDto);
return new PostResponseDto(post);
}
public void update(PostRequsetDto requsetDto) {
this.title = requsetDto.getTitle();
this.content = requsetDto.getContent();
}
//게시물 삭제
@DeleteMapping("/{postid}")
public void deletePost(@PathVariable Long postid){
postService.deletePost(postid);
}
//게시물 삭제
public void deletePost(Long postid) {
Post post = postRepository.findById(postid).orElseThrow(() -> new IllegalArgumentException("존재하지 않는 id 입니다."));
postRepository.delete(post);
}
Post
package com.sparta.newsfeed.entity;
import com.sparta.newsfeed.dto.PostRequsetDto;
import com.sparta.newsfeed.dto.PostResponseDto;
import com.sparta.newsfeed.user.entity.User;
import com.sparta.newsfeed.user.security.UserDetailsImpl;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import java.time.LocalDateTime;
@Entity
@Getter
@NoArgsConstructor
@Table(name = "posts")
public class Post extends TimeEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@Column(nullable = false)
private String content;
@Column(nullable = false)
private String username;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
public Post(PostRequsetDto requsetDto, UserDetailsImpl userDetails){
this.title = requsetDto.getTitle();
this.content = requsetDto.getContent();
this.user = userDetails.getUser();
this.username = userDetails.getUsername();
}
public void update(PostRequsetDto requsetDto) {
this.title = requsetDto.getTitle();
this.content = requsetDto.getContent();
}
}
PostResponseDto
package com.sparta.newsfeed.dto;
import com.sparta.newsfeed.entity.Post;
import lombok.Getter;
import lombok.Setter;
import org.springframework.cglib.core.Local;
import java.time.LocalDateTime;
@Getter
@Setter
public class PostResponseDto {
private Long id;
private String title;
private String content;
private String username;
private LocalDateTime createdDate;
private LocalDateTime modifiedDate;
public PostResponseDto(Post post){
this.id = post.getId();
this.title = post.getTitle();
this.content= post.getContent();
this.username = post.getUsername();
this.createdDate = post.getCreatedDate();
this.modifiedDate = post.getModifiedDate();
}
}
PostController
package com.sparta.newsfeed.controller;
import com.sparta.newsfeed.dto.PostRequsetDto;
import com.sparta.newsfeed.dto.PostResponseDto;
import com.sparta.newsfeed.service.PostService;
import com.sparta.newsfeed.user.security.UserDetailsImpl;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Controller
@RequestMapping("/api/posts")
public class PostController {
private final PostService postService;
public PostController(PostService postService) {
this.postService = postService;
}
//게시물 생성
@PostMapping("/create")
public String createPost(@RequestBody PostRequsetDto requsetDto, @AuthenticationPrincipal UserDetailsImpl userDetails){
postService.createPost(requsetDto, userDetails);
return "redirect:/api/posts";
}
//작성자의 전체 게시물 조회
@ResponseBody
@GetMapping("/userId/{userId}")
public List<PostResponseDto> getPostsByUserId(@PathVariable Long userId, @AuthenticationPrincipal UserDetailsImpl userDetails){
return postService.getPostsByUserId(userId, userDetails);
}
//게시물 1건 조회
@ResponseBody
@GetMapping("/postId/{postId}")
public PostResponseDto getOnePost(@PathVariable Long postId){
return postService.getOnePost(postId);
}
//게시물 전체 조회
@ResponseBody
@GetMapping
public List<PostResponseDto> getAllPost(){
return postService.getAllPost();
}
//게시물 수정
@PutMapping("/{postid}")
public String updatePost(@PathVariable Long postid, @RequestBody PostRequsetDto requsetDto, @AuthenticationPrincipal UserDetailsImpl userDetails){
postService.updatePost(postid, requsetDto, userDetails);
return "redirect:/api/posts";
}
//게시물 삭제
@DeleteMapping("/{postid}")
public String deletePost(@PathVariable Long postid, @AuthenticationPrincipal UserDetailsImpl userDetails){
postService.deletePost(postid, userDetails);
return "redirect:/api/posts";
}
}
PosetService
package com.sparta.newsfeed.service;
import com.sparta.newsfeed.dto.PostRequsetDto;
import com.sparta.newsfeed.dto.PostResponseDto;
import com.sparta.newsfeed.entity.Post;
import com.sparta.newsfeed.repository.PostRepository;
import com.sparta.newsfeed.user.entity.User;
import com.sparta.newsfeed.user.security.UserDetailsImpl;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.RejectedExecutionException;
@Service
public class PostService {
private final PostRepository postRepository;
private final CommentService commentService;
public PostService(PostRepository postRepository, CommentService commentService) {
this.postRepository = postRepository;
this.commentService = commentService;
}
//게시물 생성
public PostResponseDto createPost(PostRequsetDto requsetDto, UserDetailsImpl userDetails) {
Post post = new Post(requsetDto, userDetails);
postRepository.save(post);
return new PostResponseDto(post);
}
//게시물 1건 조회
public PostResponseDto getOnePost(Long postid) {
Post post = postRepository.findById(postid).orElseThrow(() -> new IllegalArgumentException("존재하지 않는 id 입니다."));
return new PostResponseDto(post);
}
//게시물 전체 조회
public List<PostResponseDto> getAllPost() {
List<Post> postList = postRepository.findAll(Sort.by(Sort.Direction.DESC, "modifiedDate"));
List<PostResponseDto> responseDtoList = new ArrayList<>();
for(Post post : postList){
responseDtoList.add(new PostResponseDto(post));
}
return responseDtoList;
}
//게시물 수정
@Transactional
public PostResponseDto updatePost(Long postid, PostRequsetDto requsetDto, UserDetailsImpl userDetails) {
Post post = postRepository.findById(postid).orElseThrow(() -> new IllegalArgumentException("존재하지 않는 id 입니다."));
if(!userDetails.getUsername().equals(post.getUsername())){
throw new RejectedExecutionException("게시물의 작성자만 수정이 가능합니다.");
}
post.update(requsetDto);
return new PostResponseDto(post);
}
//게시물 삭제
@Transactional
public void deletePost(Long postid, UserDetailsImpl userDetails) {
Post post = postRepository.findById(postid).orElseThrow(() -> new IllegalArgumentException("존재하지 않는 id 입니다."));
if(!userDetails.getUsername().equals(post.getUsername())){
throw new RejectedExecutionException("게시물의 작성자만 삭제가 가능합니다.");
}
commentService.deleteCommentByPostId(postid);
postRepository.delete(post);
}
//작성자의 전체 게시물 조회
public List<PostResponseDto> getPostsByUserId(Long userId, UserDetailsImpl userDetails) {
if(!userId.equals(userDetails.getUser().getId())){
throw new RejectedExecutionException("가입된 유저가 아닙니다.");
}
List<Post> posts = postRepository.findByUserId(userId);
List<PostResponseDto> responseDtoList = new ArrayList<>();
for (Post post : posts) {
responseDtoList.add(new PostResponseDto(post));
}
return responseDtoList;
}
}
PostRepository
package com.sparta.newsfeed.repository;
import com.sparta.newsfeed.entity.Post;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.Optional;
public interface PostRepository extends JpaRepository<Post, Long> {
List<Post> findByUserId(Long userId);
}