코드 그라데이션

입문 과제 라이브코딩 (2) 완성한 코드 본문

Spring/CRUD 연습

입문 과제 라이브코딩 (2) 완성한 코드

완벽한 장면 2023. 2. 4. 11:52

Entity

Post

@Entity
@Getter
@NoArgsConstructor
public class Post extends TimeStamped {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)

    private Long id;
    private String title;
    private String writer;
    private String password;
    private String content;

    // public Board() {} // 기본 생성자는 반드시 있어야 한다.

    public Post(String title, String writer, String password, String content) {
        this.title = title;
        this.writer = writer;
        this.password = password;
        this.content = content;
    } // 게시판 생성 - 제목, 글쓴이, 비밀번호, 내용 => 이렇게 네 개의 요소

    public void update(String title, String writer, String content) {
        this.title = title;
        this.writer = writer;
        this.content = content;
    } // 게시글 업데이트(수정) 로직 / 제목, 작성자명, 작성 내용을 수정

    //비밀번호 검증 로직
    public boolean isValidPassword(String inputPassword) {
        if (inputPassword.equals(this.password)) {
            return true;
        } else {
            return false;
        }
    }
}

 

TimeStamped

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class TimeStamped {
    @CreatedDate
    private LocalDateTime createdAt;

    @LastModifiedDate
    private LocalDateTime modifiedAt;
}

 

DTO

PostResponse

@Getter
@NoArgsConstructor
public class PostResponse {
    private String title;
    private String writer;
    private String content;

    private LocalDateTime createdAt;

    private LocalDateTime modifiedAt;


    public PostResponse(Post post) {
        this.title = post.getTitle();
        this.writer = post.getWriter();
        this.content = post.getContent();
        this.createdAt = post.getCreatedAt();
        this.modifiedAt = post.getModifiedAt();
    }
}

 

CreatePostRequest

@Getter
@NoArgsConstructor // 기본생성자 생성과 동일
public class CreatePostRequest {
    private String title;
    private String writer;
    private String password;
    private String content;

    //@Getter와 @NoArgsConstructor가 합쳐져서 @Setter 없어도 값이 title, writer, password, content에 꽂힌다.

    //public CreateBoardRequest() {} => NoArgsConstructor로 치환.

    public CreatePostRequest(String title, String writer, String password, String content) {
        this.title = title;
        this.writer = writer;
        this.password = password;
        this.content = content;
    }
}

 

UpdatePostRequest

@Getter
@NoArgsConstructor
public class UpdatePostRequest {
    private String title;
    private String writer;
    private String content;
    private String password;

    public UpdatePostRequest(String title, String writer, String content, String password) {
        this.title = title;
        this.writer = writer;
        this.content = content;
        this.password = password;
    }
}

 

DeletePostRequest

@Getter
@NoArgsConstructor
public class DeletePostRequest {

    private String password;

    public DeletePostRequest(String password) {
        this.password = password;
    }
}

 

Controller

PostController

@RestController
@RequiredArgsConstructor
public class PostController {
    private final PostService postService;

    // 게시물 생성
    @PostMapping("/api/posts")
    //CreateBoardRequest 의 값을 전달 받음.
    public void createPost(@RequestBody CreatePostRequest createPostRequest) {
        postService.createPost(createPostRequest);
    }

    // 전체 게시물 조회
    @GetMapping("/api/posts")
    public List<PostResponse> getPostList() {
        return postService.getPostList();
    }

    // 게시물 1개 조회
    ///api/posts/1
    @GetMapping("/api/posts/{postId}")
    public PostResponse getPost(@PathVariable Long postId) {
      return postService.getPost(postId);
    }

    // 게시물 1개 수정
    @PutMapping("/api/posts/{postId}")
    public void updatePost(@PathVariable Long postId, @RequestBody UpdatePostRequest updatePostRequest) {
        postService.updatePost(postId, updatePostRequest);
    }

    // 게시물 삭제
    @DeleteMapping("/api/posts/{postId}")
    public void deletePost(@PathVariable Long postId, @RequestBody DeletePostRequest deletePostRequest) {
        postService.deletePost(postId, deletePostRequest);
    }
}

 

Service

PostService

@Service // 이게 없으면 서버가 안 뜬다.
public class PostService {
    private final PostRepository postRepository;
    // Repository를 상속받은 이 인터페이스는 DB처럼 동작한다. DB에게 시킬 때 얘한테 시키면 된다.

    public PostService(PostRepository postRepository) {
        this.postRepository = postRepository;
    } 

    // 게시글 전체 조회 
    @Transactional
    public List<PostResponse> getPostList() {
        // 작성 날짜 기준 내림차순으로 정리하기 ==> 게시물 작성 최신순으로 정렬해 내놓으란 뜻.
        List<Post> postList = postRepository.findAllByOrderByCreatedAtDesc();
        List<PostResponse> postResponseList = new ArrayList<>();
        for (Post post : postList) {
            postResponseList.add(new PostResponse((post)));
        }
        return postResponseList;
    }

    @Transactional
    // 게시글 생성 로직
    public void createPost(CreatePostRequest createPostRequest) {
        Post post = new Post(createPostRequest.getTitle(), createPostRequest.getWriter(), createPostRequest.getPassword(), createPostRequest.getContent());
        postRepository.save(post);
    }

    @Transactional
    // 게시글 조회 로직
    public PostResponse getPost(Long postId) {
        Post post = postRepository.findById(postId).orElseThrow(() -> new IllegalArgumentException("id 없음"));
        return new PostResponse(post);
    }

    // 게시글 수정 로직
    @Transactional
    public void updatePost(Long postId, UpdatePostRequest updatePostRequest) {
        Post postSaved = postRepository.findById(postId).orElseThrow(() -> new IllegalArgumentException("id 없음"));
        //    boardSaved.update(updateBoardRequest.getTitle(), updateBoardRequest.getWriter(), updateBoardRequest.getContent());
        //  추가요건 : 수정요청 시 수정 데이터와 비밀번호를 함께 보내서 서버에서 비밀번호 일치 여부 확인 후 업데이트 해라.
        // 이게 앞서 넣어놓은(Board 에다가) 비밀번호 유효성 검사.
        if (postSaved.isValidPassword(updatePostRequest.getPassword())) {
            postSaved.update(updatePostRequest.getTitle(), updatePostRequest.getWriter(), updatePostRequest.getContent());
            postRepository.save(postSaved);
        } else {
            throw new IllegalArgumentException("패스워드가 틀렸습니다!");
        }
    }

    // 게시글 삭제 로직
    @Transactional
    public void deletePost(Long postId, DeletePostRequest deletePostRequest) {
        Post postDelete = postRepository.findById(postId).orElseThrow(() -> new IllegalArgumentException("id 없음"));
        String password = deletePostRequest.getPassword();
        if (postDelete.isValidPassword(password)) {
            postRepository.delete(postDelete); //delete는 JPA에서 직접 제공 => 쿼리 직접 날려준다
            System.out.println("삭제에 성공했습니다.");
        } else {
            throw new IllegalArgumentException("패스워드가 다릅니다!");
        }
    }

}

 

 

Repository

PostRepository

public interface PostRepository extends JpaRepository<Post, Long> {

    List<Post> findAllByOrderByCreatedAtDesc();

}
728x90
Comments