[과제] 게시판 만들기 - CRUD

느려도 꾸준히·2023년 10월 30일

과제

목록 보기
1/3

Spring Lv.1

"스파르타 익명 게시판 서버 만들기"

🚩! 요구사항 확인: 필수 구현 기능

  1. 게시글 작성 기능
    • 제목, 작성자명, 비밀번호, 작성 내용, 작성일을 저장할 수 있습니다.
    • 저장된 게시글의 정보를 반환 받아 확인할 수 있습니다.
      • 반환 받은 게시글의 정보에 비밀번호는 제외 되어있습니다.
  1. 선택한 게시글 조회 기능
    • 선택한 게시글의 정보를 조회할 수 있습니다.
      • 반환 받은 게시글의 정보에 비밀번호는 제외 되어있습니다.
  1. 게시글 목록 조회 기능
    • 등록된 게시글 전체를 조회할 수 있습니다.
      • 반환 받은 게시글의 정보에 비밀번호는 제외 되어있습니다.
    • 조회된 게시글 목록은 작성일 기준 내림차순으로 정렬 되어있습니다.
  1. 선택한 게시글 수정 기능
    • 선택한 게시글의 제목, 작성자명, 작성 내용을 수정할 수 있습니다.
      • 서버에 게시글 수정을 요청할 때 비밀번호를 함께 전달합니다.
      • 선택한 게시글의 비밀번호와 요청할 때 함께 보낸 비밀번호가 일치할 경우에만 수정이 가능합니다.
    • 수정된 게시글의 정보를 반환 받아 확인할 수 있습니다.
      • 반환 받은 게시글의 정보에 비밀번호는 제외 되어있습니다.
  1. 선택한 게시글 삭제 기능
    • 선택한 게시글을 삭제할 수 있습니다.
      • 서버에 게시글 삭제를 요청할 때 비밀번호를 함께 전달합니다.
      • 선택한 게시글의 비밀번호와 요청할 때 함께 보낸 비밀번호가 일치할 경우에만 삭제가 가능합니다.
  • < Use Case Diagram >

  • < API 명세서 >

  • < ERD >

- Board

package com.sparta.board.entity;


import com.sparta.board.dto.BoardRequestDto;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.time.LocalDateTime;

@Entity  // JPA가 관리할 수 있는 Entity 클래스 지정
@Getter
@Setter
@Table(name = "board")  // 매핑할 테이블의 이름을 지정
@NoArgsConstructor
public class Board extends Timestamped {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; // id

    @Column(name = "title", nullable = false)
    private String title; // 제목

    @Column(name = "username", nullable = false)
    private String username; // 작성자명

    @Column(name = "password", nullable = false)
    private String password; // 비밀번호

    @Column(name = "contents", nullable = false, length = 500)
    private String contents; // 작성내용

    public Board(BoardRequestDto requestDto) {
        this.title = requestDto.getTitle();
        this.username = requestDto.getUsername();
        this.password = requestDto.getPassword();
        this.contents = requestDto.getContents();
    }

    public void update(BoardRequestDto requestDto) {
        this.title = requestDto.getTitle();
        this.username = requestDto.getUsername();
    //    this.password = requestDto.getPassword();
        this.contents = requestDto.getContents();
    }
}

- Controller

package com.sparta.board.controller;


import com.sparta.board.dto.BoardRequestDto;
import com.sparta.board.dto.BoardResponseDto;
import com.sparta.board.service.BoardService;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api")
public class BoardController {

    private final BoardService boardService;
    public BoardController(BoardService boardService) {
        this.boardService = boardService;
    }

    @PostMapping("/boards") //게시글 작성
    public BoardResponseDto createBoard(@RequestBody BoardRequestDto requestDto) {
        return boardService.createBoard(requestDto);
    }

    @GetMapping("/boards/{id}") // 게시글 조회
    public BoardResponseDto getBoard(@PathVariable Long id) {
        return boardService.getBoard(id);
    }

    @GetMapping("/boards") // 게시글 목록 조회
    public List<BoardResponseDto> getBoards() {
        return boardService.getBoards();
    }

    @PutMapping("/boards/{id}") // 게시글 수정
    public BoardResponseDto updateBoard(@PathVariable Long id, @RequestBody BoardRequestDto requestDto) {
        return boardService.updateBoard(id, requestDto.getPassword(), requestDto);
    }

    @DeleteMapping("/boards/{id}") // 게시글 삭제
    public Long deleteBoard(@PathVariable Long id, @RequestBody BoardRequestDto requestDto) {
        return boardService.deleteBoard(id, requestDto.getPassword());
    }
}

.

- Service

package com.sparta.board.service;

import com.sparta.board.dto.BoardRequestDto;
import com.sparta.board.dto.BoardResponseDto;
import com.sparta.board.entity.Board;
import com.sparta.board.repository.BoardRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class BoardService {

    private final BoardRepository boardRepository;

    public BoardService(BoardRepository boardRepository) {
        this.boardRepository = boardRepository;
    }

    public BoardResponseDto createBoard(BoardRequestDto requestDto) {
        // RequestDto -> Entity
        Board board = new Board(requestDto);

        // DB 저장
        Board saveBoard = boardRepository.save(board);  // boardRepository 사용

        // Entity -> ResponseDto
        BoardResponseDto boardResponseDto = new BoardResponseDto(saveBoard);

        return boardResponseDto;
    }

    public BoardResponseDto getBoard(Long id) {
        Board board = boardRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("해당 게시글이 없습니다. id=" + id));
        return new BoardResponseDto(board);
    }


    public List<BoardResponseDto> getBoards() {
        // DB 조회
        return boardRepository.findAllByOrderByModifiedAtDesc().stream().map(BoardResponseDto::new).toList();
    }

    @Transactional
    public BoardResponseDto updateBoard(Long id, String password, BoardRequestDto requestDto) {
        // 해당 게시글이 DB에 존재하는지 확인
        Board board = boardRepository.findById(id).orElseThrow(
                () -> new IllegalArgumentException("해당 게시글이 없습니다. id=" + id)
        );

        if (!board.getPassword().equals(password)) {
            throw new IllegalArgumentException("비밀번호가 틀렸습니다.");
        }

        board.update(requestDto);
        return new BoardResponseDto(board);
    }

    public Long deleteBoard(Long id, String password) {
        // 해당 게시글이 DB에 존재하는지 확인
        Board board = boardRepository.findById(id).orElseThrow(
                () -> new IllegalArgumentException("해당 게시글이 없습니다. id=" + id)
        );

        if (!board.getPassword().equals(password)) {
            throw new IllegalArgumentException("비밀번호가 틀렸습니다.");
        }

        boardRepository.delete(board);
        return id;
    }

    private Board findBoard(Long id) {
        return boardRepository.findById(id).orElseThrow(() ->
                new IllegalArgumentException("선택한 게시글은 존재하지 않습니다.")
        );
    }
}

.

- Repository

package com.sparta.board.repository;

import com.sparta.board.entity.Board;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;


public interface BoardRepository extends JpaRepository<Board,Long> {
    List<Board> findAllByOrderByModifiedAtDesc();
}

.

- RequestDto

package com.sparta.board.dto;


import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
public class BoardRequestDto {
    private String title;
    private String username;
    private String password;
    private String contents;

    public BoardRequestDto(String title, String username, String password, String contents) {
        this.title = title;
        this.username = username;
        this.password = password;
        this.contents = contents;
    }
}

.

- ResponseDto

package com.sparta.board.dto;

import com.sparta.board.entity.Board;
import lombok.Getter;

import java.time.LocalDateTime;

@Getter
public class BoardResponseDto {
    private Long id;
    private String title;
    private String username;
    private String contents;
    private LocalDateTime createdAt;
    private LocalDateTime modifiedAt;

    public BoardResponseDto(Board board) {
        this.id = board.getId();
        this.title = board.getTitle();
        this.username = board.getUsername();
        this.contents = board.getContents();
        this.createdAt = board.getCreatedAt();
        this.modifiedAt = board.getModifiedAt();
    }
}

.

- Timestamped

package com.sparta.board.entity;

import jakarta.persistence.*;
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 abstract class Timestamped {

    @CreatedDate
    @Column(updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private LocalDateTime createdAt;

    @LastModifiedDate
    @Column
    @Temporal(TemporalType.TIMESTAMP)
    private LocalDateTime modifiedAt;
}

0개의 댓글