board의 username을 User에서 가져오도록 만들어본다
하나의 유저는 여러 개의 게시판을 만들 수 있다.
그러므로 OneToMany를 사용하고, Board를 list로 가져온다.
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.sparta.BoardAPI2.dto.UserRequestDto;
import lombok.*;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity //db테이블과 일대일로 매핑
@Table(name = "users") // 테이블명 지정
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User {
@Id
@Column(name = "user_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long userId;
@Column(length = 50, unique = true)
private String username;
@Column(length = 100)
private String password;
@JsonIgnore
@OneToMany(mappedBy = "user")
List<Board> board = new ArrayList<>();
public User(UserRequestDto requestDto) {
this.username = requestDto.getUsername();
this.password = requestDto.getPassword();
}
}
필요한 엔티티를 매핑한다
Board - User : Board는 여러개를 하나의 유저가 가질 수 있으므로 ManyToOne이다.
Board - Comment : Board하나는 여러 개의 게시글을 가질 수 있으므로 OneToMany이다.
생성자에 매개변수로 필요한 엔티티를 추가한다.
package com.sparta.BoardAPI2.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.sparta.BoardAPI2.dto.BoardRequestDto;
import com.sparta.BoardAPI2.security.UserDetailsImpl;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Setter
@Getter // get 함수를 일괄적으로 만들어줍니다.
@NoArgsConstructor // 기본 생성자를 만들어줍니다.
@Entity // DB 테이블 역할을 합니다.
public class Board extends Timestamped {
// 글 고유 아이디
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
@Column(name = "boardId")
private Long id;
// 글 제목
@Column(nullable = false)
private String title;
// 글 내용
@Column(nullable = false)
private String content;
// 비밀번호
@Column(nullable = false)
private String password;
@ManyToOne
@JoinColumn(name = "userId")
private User user;
@JsonIgnore
@OneToMany(mappedBy = "board")
List<Comment> comments = new ArrayList<>();
// requestDto 정보를 가져와서 entity 만들 때 사용 (user매핑)
public Board(User user, BoardRequestDto requestDto) {
this.title = requestDto.getTitle();
this.content = requestDto.getContent();
this.password = requestDto.getPassword();
this.user = user;
}
// 업데이트 메소드
public void update(BoardRequestDto requestDto) {
this.title = requestDto.getTitle();
this.content = requestDto.getContent();
this.password = requestDto.getPassword();
}
}
package com.sparta.BoardAPI2.dto;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@NoArgsConstructor
@Getter
@Setter
public class BoardRequestDto {
private String title;
private String content;
private String password;
}
import com.sparta.BoardAPI2.entity.Board;
import com.sparta.BoardAPI2.entity.User;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@NoArgsConstructor
@Getter
public class BoardResponseDto {
private String title;
private String content;
private LocalDateTime createdAt;
private LocalDateTime modifiedAt;
private String username;
// board의 정보를 받아 boardResponseDto 생성
public BoardResponseDto(User user, Board board) {
this.username = user.getUsername();
this.title = board.getTitle();
this.content = board.getContent();
this.createdAt = board.getModifiedAt();
this.modifiedAt = board.getCreatedAt();
}
public BoardResponseDto(Board board) {
this.title = board.getTitle();
this.content = board.getContent();
this.createdAt = board.getModifiedAt();
this.modifiedAt = board.getCreatedAt();
this.username = board.getUser().getUsername();
}
}
생성자에서 User을 받을 필요가 없는 이유는, Board에 user이 매핑되어있기 때문에 board.getUser()로 가져오면 되기 때문이다.
import com.sparta.BoardAPI2.entity.Board;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@NoArgsConstructor
@AllArgsConstructor
@Getter
public class BoardListResponseDto {
// 제목
private String title;
// 작성자명
private String username;
private LocalDateTime createdAt;
private LocalDateTime modifiedAt;
// Entity -> dto
public BoardListResponseDto(Board board) {
this.username = board.getUser().getUsername();
this.title = board.getTitle();
this.createdAt = board.getModifiedAt();
this.modifiedAt = board.getCreatedAt();
}
}
import com.sparta.BoardAPI2.dto.BoardListResponseDto;
import com.sparta.BoardAPI2.dto.BoardRequestDto;
import com.sparta.BoardAPI2.dto.BoardResponseDto;
import com.sparta.BoardAPI2.entity.Board;
import com.sparta.BoardAPI2.entity.User;
import com.sparta.BoardAPI2.repository.BoardRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.List;
@RequiredArgsConstructor
@Service
public class BoardService {
private final BoardRepository boardRepository;
// 글 생성 (user 매핑)
public BoardResponseDto createBoard(User user, BoardRequestDto requestDto) {
Board board = new Board(user, requestDto);
boardRepository.save(board);
return new BoardResponseDto(user, board);
}
// 글 목록 가져오기
public List<BoardListResponseDto> findAllBoard() {
return boardRepository.findAllByOrderByModifiedAtDesc();
}
// 글 하나 가져오기
public BoardResponseDto findOneBoard(Long id) {
Board board = boardRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException("게시글이 없습니다")
);
return new BoardResponseDto(board);
}
// 글 수정
@Transactional
public Long updateBoard(User user, Long id, BoardRequestDto requestDto) {
// 어떤 게시판인지 찾기
Board board = boardRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException("해당 게시글이 존재하지 않습니다.")
);
// 게시판의 username과 로그인 유저의 username 비교
if (user.getUsername().equals(board.getUser().getUsername())) {
board.update(requestDto);
return board.getId();
} else {
throw new IllegalArgumentException("작성자만 수정할 수 있습니다");
}
}
// 삭제
@Transactional
public Long deleteBoard(User user, Long id) {
// 어떤 게시판인지 찾기
Board board = boardRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException("해당 게시글이 존재하지 않습니다.")
);
// 게시판의 username과 로그인 유저의 username 비교
if (user.getUsername().equals(board.getUser().getUsername())) {
boardRepository.deleteById(id);
return id;
} else {
throw new IllegalArgumentException("작성자만 수정할 수 있습니다");
}
}
// 비밀번호 일치 확인
public boolean checkPassword(Long id, String inputPassword) {
Board board = boardRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException("해당 아이디가 존재하지 않습니다.")
);
if (inputPassword.equals(board.getPassword())) {
return true;
} else {
return false;
}
}
}
@AuthenticationPrincipal 어노테이션으로 UserDetailsImpl에서 로그인한 유저 정보를 가져올 수 있다.
UserDetailsImpl에서 필드와 생성자로 User의 데이터를 연결시켰기 때문에, userDetails.getUser()로 유저 데이터를 가져올 수 있다.
import com.sparta.BoardAPI2.dto.BoardListResponseDto;
import com.sparta.BoardAPI2.dto.BoardRequestDto;
import com.sparta.BoardAPI2.dto.BoardResponseDto;
import com.sparta.BoardAPI2.entity.Board;
import com.sparta.BoardAPI2.security.UserDetailsImpl;
import com.sparta.BoardAPI2.service.BoardService;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController // JSON으로 데이터를 주고받음을 선언합니다.
public class BoardController {
private final BoardService boardService;
public BoardController(BoardService boardService) {
this.boardService = boardService;
}
// 글 등록
@PostMapping("/boards")
public BoardResponseDto createBoard(@AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody BoardRequestDto requestDto) {
return boardService.createBoard(userDetails.getUser(), requestDto);
}
// 글 등록
// @PostMapping("/boards")
// public BoardResponseDto createBoard(@RequestBody BoardRequestDto requestDto){
// BoardResponseDto board = boardService.createBoard(requestDto);
// return board;
// }
// 전체 목록 조회
@GetMapping("/boards-list")
public List<BoardListResponseDto> getAllBoards() {
return boardService.findAllBoard();
}
// 글 하나 조회
@GetMapping("/boards/{id}")
public BoardResponseDto getOneBoard(@PathVariable Long id) {
return boardService.findOneBoard(id);
}
// 글 수정
@PutMapping("/boards/{id}")
public Long updateBoard(@AuthenticationPrincipal UserDetailsImpl userDetails, @PathVariable Long id, @RequestBody BoardRequestDto requestDto) {
return boardService.updateBoard(userDetails.getUser(), id, requestDto);
}
// 글 삭제
@DeleteMapping("/boards/{id}")
public Long deleteBoard(@AuthenticationPrincipal UserDetailsImpl userDetails, @PathVariable Long id) {
return boardService.deleteBoard(userDetails.getUser(), id);
}
// 비밀번호 확인
@GetMapping("/boards/check/{id}/{inputPassword}")
public boolean checkPassword(@PathVariable Long id, @PathVariable String inputPassword) {
return boardService.checkPassword(id, inputPassword);
}
}
board의 id를 가져오도록 board를 조인시켜준다.
import com.sparta.BoardAPI2.dto.CommentRequestDto;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Getter
@NoArgsConstructor
@Entity
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// @Column(nullable = false)
// private Long boardId;
@Column(nullable = false)
private String content;
@ManyToOne
@JoinColumn(name = "boardId")
private Board board;
public Comment(CommentRequestDto requestDto, Board board) {
this.content = requestDto.getContent();
// this.boardId = requestDto.getBoardId();
this.board = board;
}
public void update(CommentRequestDto requestDto) {
this.content = requestDto.getContent();
}
}
작성 내용과 board의 id를 받는다.
id는 comment에서 저장했던 board를 get시켜서 id를 또 get한다.
import com.sparta.BoardAPI2.entity.Comment;
import lombok.Getter;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@Getter
public class CommentRequestDto {
private String content;
private Long boardId;
public CommentRequestDto(Comment comment) {
this.content = comment.getContent();
this.boardId = comment.getBoard().getId();
}
}
응답을 보낼 데이터 중 어떤 데이터를 보여줄지 선택해서 필드에 넣는다.
생성자를 만들 때, comment.getUser.getUsername() 처럼 만들었던 comment entity에 있는 user과 board에 접근해서 각각의 getter를 사용할 수 있다.
import com.sparta.BoardAPI2.entity.Comment;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Getter
public class CommentResponseDto {
private Long boardId;
private String content;
public CommentResponseDto(Comment comment) {
this.content = comment.getContent();
this.boardId = comment.getBoard().getId();
}
}
commentRepositoryDto에서 boardId로 찾을것이기 때문에 만들어준다
import com.sparta.BoardAPI2.dto.CommentResponseDto;
import com.sparta.BoardAPI2.entity.Comment;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface CommentRepository extends JpaRepository<Comment, Long> {
List<CommentResponseDto> findAllByBoardId(Long boardId);
}
import com.sparta.BoardAPI2.dto.CommentRequestDto;
import com.sparta.BoardAPI2.dto.CommentResponseDto;
import com.sparta.BoardAPI2.entity.Board;
import com.sparta.BoardAPI2.entity.Comment;
import com.sparta.BoardAPI2.repository.BoardRepository;
import com.sparta.BoardAPI2.repository.CommentRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.List;
@RequiredArgsConstructor
@Service
public class CommentService {
private final CommentRepository commentRepository;
private final BoardRepository boardRepository;
// 댓글 등록 기본
// @Transactional
// public CommentResponseDto createComment(CommentRequestDto requestDto) {
// Comment comment = new Comment(requestDto);
// commentRepository.save(comment);
// CommentResponseDto commentResponseDto = new CommentResponseDto(comment);
// return commentResponseDto;
// }
// 댓글 등록 board 매핑
@Transactional
public CommentResponseDto createComment(CommentRequestDto requestDto, Long id) {
Board board = boardRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException("조회 실패"));
Comment comment = new Comment(requestDto,board);
commentRepository.save(comment);
CommentResponseDto commentResponseDto = new CommentResponseDto(comment);
return commentResponseDto;
}
// 전체 댓글 조회
@Transactional
public List<CommentResponseDto> readAllComments(Long id) {
return commentRepository.findAllByBoardId(id);
}
}
import com.sparta.BoardAPI2.dto.CommentRequestDto;
import com.sparta.BoardAPI2.dto.CommentResponseDto;
import com.sparta.BoardAPI2.service.CommentService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RequiredArgsConstructor
@RestController
public class CommentController {
private final CommentService commentService;
// 댓글 등록
@PostMapping("/boards/{id}/comments")
public CommentResponseDto createBoard(@RequestBody CommentRequestDto requestDto, @PathVariable Long id) {
return commentService.createComment(requestDto, id);
}
// 댓글 목록 조회
@GetMapping("/boards/{id}/comments-list")
public List<CommentResponseDto> getAllComments(@PathVariable Long id) {
return commentService.readAllComments(id);
}
}
문제 상황 : 어플리케이션 실행이 안 됨
해결 : SecurityConfig 관련 파일이 두개였음, 하나를 삭제
UserRequestDto 클래스 작성 부탁드려요~^^