Intellij IDEA Community
mysql 8.0.34
Spring Data JPA
JDK 11
SpringBoot 2.6.13
create, research, update, delete 의 약자로 기본적인 게시판 기능을 말하는 것
@SpringBootApplication
public class BoardApplication {
public static void main(String[] args) {
SpringApplication.run(BoardApplication.class, args);
}
}
스프링 부트를 초기화시키고, 스프링 부트 어플리케이션을 선정함.
@Controller
public class HomeController {
@GetMapping("/")
public String index() {
return "index";
}
}
http://localhost:8080/ 경로에 대한 메핑을 받아서 index 실행
@Controller
@RequiredArgsConstructor
@RequestMapping("/board")
public class BoardController {
private final BoardService boardService;
@GetMapping("/save") //작성 화면
public String saveForm(){
return "save";
}
@PostMapping("/save") //게시글 저장
public String save(@ModelAttribute BoardDTO boardDTO){
boardService.save(boardDTO);
return "index";
}
@GetMapping("/") //모든 게시글 목록
public String findAll(Model model){
List<BoardDTO> boardDTOList = boardService.findAll();
model.addAttribute("boardList",boardDTOList);
return "list";
}
@GetMapping("/{id}") // 상세조회
public String findById(@PathVariable Long id, Model model){
boardService.updateHits(id); //조회수 +1
BoardDTO boardDTO = boardService.findById(id); //실제 찾아오기
model.addAttribute("board",boardDTO);
return "detail";
}
@GetMapping("/update/{id}") //수정된 부분 수정후 화면 출력
public String updateForm(@PathVariable Long id, Model model){
BoardDTO boardDTO = boardService.findById(id);
model.addAttribute("boardUpdate",boardDTO);
return "update";
}
@PostMapping("/update") //게시물 수정
public String update(@ModelAttribute BoardDTO boardDTO, Model model){
BoardDTO board = boardService.update(boardDTO);
model.addAttribute("board",board);
return "detail"; //수정이 완료된 상세 페이지
}
@GetMapping("/delete/{id}") //게시글 삭제
public String delete(@PathVariable Long id){
boardService.delete(id);
return "redirect:/board/";
}
}
requestmapping("/board")을 이용해서 각 url, 다른 type의 매핑들 경우에서의 메서드들을 호출
@Service
@RequiredArgsConstructor
public class BoardService {
private final BoardRepository boardRepository;
public void save(BoardDTO boardDTO) {
BoardEntity boardEntity = BoardEntity.toSaveEntity(boardDTO);
boardRepository.save(boardEntity);
}
public List<BoardDTO> findAll() {
// 레포지토리에서 entity 가져오기
List<BoardEntity> boardEntityList = boardRepository.findAll();
List<BoardDTO> boardDTOList = new ArrayList<>();
for(BoardEntity boardEntity : boardEntityList){
boardDTOList.add(BoardDTO.toBoardDTO(boardEntity));
}
return boardDTOList;
}
@Transactional
public void updateHits(Long id) {
boardRepository.updateHits(id);
}
public BoardDTO findById(Long id) {
Optional<BoardEntity> optionalBoardEntity = boardRepository.findById(id);
if (optionalBoardEntity.isPresent()){
BoardEntity boardEntity = optionalBoardEntity.get();
return BoardDTO.toBoardDTO(boardEntity);
}else{
return null;
}
}
public BoardDTO update(BoardDTO boardDTO) { //update용 엔티티
BoardEntity boardEntity = BoardEntity.toUpdateEntity(boardDTO);
boardRepository.save(boardEntity);
return findById(boardDTO.getId());
}
public void delete(Long id) {
boardRepository.deleteById(id);
}
}
각종 기능을 구현하는 부분
findall 할 때는 레포지토리에서 엔티티를 받아와서 Dto로 바꾸고 dto 바환
save는 반대로 dto를 entity로 바꾼 뒤 레포지토리에 저장
상세조회는 optional 개체로 entity를 받아와서, 해당 dto를 반환
@Getter
@Setter //get set method 자동으로 해줌
@ToString
@NoArgsConstructor //기본 생성자
@AllArgsConstructor //모든 필드 매개변수 생성자
public class BoardDTO {
private Long id;
private String boardWriter;
private String boardPass;
private String boardTitle;
private String boardContents;
private int boardHits; //조회수
private LocalDateTime boardCreatedTime; //작성 시간
private LocalDateTime boardUpdatedTime; //수정 시간
public static BoardDTO toBoardDTO(BoardEntity boardEntity) {
BoardDTO boardDTO = new BoardDTO();
boardDTO.setId(boardEntity.getId());
boardDTO.setBoardWriter(boardEntity.getBoardWriter());
boardDTO.setBoardPass(boardEntity.getBoardPass());
boardDTO.setBoardTitle(boardEntity.getBoardTitle());
boardDTO.setBoardContents(boardEntity.getBoardContents());
boardDTO.setBoardHits(boardEntity.getBoardHits());
boardDTO.setBoardCreatedTime(boardEntity.getCreatedTime());
boardDTO.setBoardUpdatedTime(boardEntity.getUpdatedTime());
return boardDTO;
}
}
entity 개체의 get 해 와서, dto 필드에 set 해줌
모델 어트리뷰트로 받아올 때 dto로 받아오는데, 이때 뷰의 필드 네임과 dto의 필드 네임이 같아야한다.
ex) BoardWriter은 save html에서 input의 네임태그도 BoardWriterd임
@Entity
@Getter
@Setter
@Table(name = "board_table")
public class BoardEntity extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 20, nullable = false)
private String boardWriter;
@Column // 기본 길이는 255
private String boardPass;
@Column
private String boardTitle;
@Column(length = 500)
private String boardContents;
@Column
private int boardHits;
public static BoardEntity toSaveEntity(BoardDTO boardDTO){
BoardEntity boardEntity = new BoardEntity();
boardEntity.setBoardWriter(boardDTO.getBoardPass());
boardEntity.setBoardContents(boardDTO.getBoardContents());
boardEntity.setBoardTitle(boardDTO.getBoardTitle());
boardEntity.setBoardPass(boardDTO.getBoardPass());
boardEntity.setBoardHits(0); //초기 조회수는 0으로 시작
return boardEntity;
}
public static BoardEntity toUpdateEntity(BoardDTO boardDTO){
BoardEntity boardEntity = new BoardEntity();
boardEntity.setId(boardDTO.getId());
boardEntity.setBoardWriter(boardDTO.getBoardPass());
boardEntity.setBoardContents(boardDTO.getBoardContents());
boardEntity.setBoardTitle(boardDTO.getBoardTitle());
boardEntity.setBoardPass(boardDTO.getBoardPass());
boardEntity.setBoardHits(boardDTO.getBoardHits()); //조회수는 기존 조회수에서 이어져야 함
return boardEntity;
}
}
Jpa가 제공하는 어노테이션을 이용해서 @Table, @Column 등의 어노테이션을 객체와 데이터베이스간의 매핑을 자동으로 처리해줌
@ID는 기본 키이다. join 참조를 할 때 주로 사용된다. @GeneratedValue 애너테이션은 주요 키의 값을 자동으로 생성한다.
strategy = GenerationType.IDENTITY는 데이터베이스의 identity 컬럼을 사용하여 자동으로 값을 생성하도록 지정함.
public interface BoardRepository extends JpaRepository<BoardEntity, Long> {
@Modifying
@Query(value = "update BoardEntity b set b.boardHits=b.boardHits+1 where b.id=:id")
void updateHits(@Param("id") Long id);
}
JpaRepository에서 제공하는 기본적인 CRUD 작업 외에도 사용자 정의 쿼리를 정의하여 데이터베이스와 상호 작용한다. updateHits 메서드는 게시글의 조회수를 증가시키는 간단한 사용자 정의 쿼리를 실행하는데 사용된다.
5주차에 1주차 얘기를 쓰는 상황이 생기긴했지만 처음에 뭐 했었는지 차근차근 다시 보는 느낌이어서 오히려 좋았던 거 같다. 회원 서비스 기능도 넣어보고 싶고, 대댓글 기능도 넣어봤으면 좋겠다. 게시물 검색기능도 목표다. 타임리프 템플릿 공부도 좀 하려고 한다.