전 게시글은 아래를 참고 해주세요.
Spring Boot JPA 게시판 - CRUD (with MySQL)
Spring Boot 게시판 프로젝트를 시작하기 위해 Database 생성하고 끝냈었다. MySQL 접속 및 database 생성 MySQL을 Docker 에 설치하였고, Spring boot 와 연동하기 전 database 를 생성해보자. Docker에 MySQL을..
mkdevlab.tistory.com
게시글을 등록/수정 할 수 있는 기능을 추가해보자.
신규 생성한 소스
- BoardRestController
- BoardService
- BoardRequestDto
- BoardResponseDto
수정한 소스
- Board (Entity)
1. Request(요청) Dto 생성
API로 요청할 때 데이터를 객체화 할 Request Dto 를 생성한다.
package com.mkdevlab.springbootboard.dto;
import com.mkdevlab.springbootboard.domain.Board;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class BoardRequestDto {
private String title;
private String content;
private String writer;
private char deleteYn;
public Board toEntity() {
return Board.builder()
.title(title)
.content(content)
.writer(writer)
.deleteYn(deleteYn)
.build();
}
}
toEntity()
Entity, 즉 테이블에 해당 값을 넣기 위해 Entity 화를 해준다고 보면 된다.
2. 응답(Response) Dto 생성
요청이 오면 DB 에서 값을 조회하고 객체에 담아주기 위해 생성한다.
package com.mkdevlab.springbootboard.dto;
import java.time.LocalDateTime;
import com.mkdevlab.springbootboard.domain.Board;
import lombok.Getter;
@Getter
public class BoardResponseDto {
private Long id;
private String title;
private String writer;
private String content;
private char deleteYn;
private int hits;
private LocalDateTime createdDate;
private LocalDateTime modifiedDate;
public BoardResponseDto(Board entity) {
this.id = entity.getId();
this.title = entity.getTitle();
this.writer = entity.getWriter();
this.content = entity.getContent();
this.deleteYn = entity.getDeleteYn();
this.hits = entity.getHits();
this.createdDate = entity.getCreatedDate();
this.modifiedDate = entity.getModifiedDate();
}
}
3. Entity 수정 기능 추가
package com.mkdevlab.springbootboard.domain;
import java.time.LocalDateTime;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // PK
private String title;
private String content;
private String writer;
private int hits;
private char deleteYn;
private LocalDateTime createdDate = LocalDateTime.now();
private LocalDateTime modifiedDate;
@Builder
public Board(String title, String content, String writer, int hits, char deleteYn) {
this.title = title;
this.content = content;
this.writer = writer;
this.hits = hits;
this.deleteYn = deleteYn;
}
public void update(String title, String content, String writer) {
this.title = title;
this.content = content;
this.writer = writer;
this.modifiedDate = LocalDateTime.now();
}
}
update() 메소드를 추가한다.
잉..? 근데 이건 그냥 Board의 값을 update 해주는 거지, 서버로 SQL 을 날리는 작업을 하는 건 보이지 않는다... WoW
4. Service 생성
package com.mkdevlab.springbootboard.service;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.mkdevlab.springbootboard.domain.Board;
import com.mkdevlab.springbootboard.dto.BoardRequestDto;
import com.mkdevlab.springbootboard.dto.BoardResponseDto;
import com.mkdevlab.springbootboard.repository.BoardRepository;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Service
public class BoardService {
private final BoardRepository boardRepository;
/*
* 게시글 생성
*/
@Transactional
public Long save(final BoardRequestDto param) {
Board entity = boardRepository.save(param.toEntity());
return entity.getId();
}
/*
* 게시글 리스트 조회
*/
public List<BoardResponseDto> findAll() {
Sort sort = Sort.by(Direction.DESC, "id", "createdDate");
List<Board> list = boardRepository.findAll(sort);
// Stream API 를 사용하지 않는 경우
List<BoardResponseDto> boardList = new ArrayList<>();
for (Board entity : list) {
boardList.add(new BoardResponseDto(entity));
}
return boardList;
//return list.stream().map(BoardResponseDto::new).collect(Collectors.toList());
}
/*
* 게시글 수정
*/
@Transactional
public Long update(final Long id, BoardRequestDto param) {
//Board entity = boardRepository.findById(id).orElseThrow(() -> new NullPointerException());
Board entity = boardRepository.findById(id).orElse(null);
if (entity == null) {
throw new NullPointerException();
}
entity.update(param.getTitle(), param.getContent(), param.getWriter());
return id;
}
}
save()
이 기능은 이 전 게시글에서 봤듯이 repository 의 save() 기능을 사용하고 있다.
findAll()
이것도 전 게시글에서 테스트 할 때 봣듯이 repository 의 findAll() 기능을 사용하고 있다.
update()
repository 의 update 기능이 없는건가? 라고 생각할 수 있는 부분인데, JPA 의 영속성 컨텍스트라는 개념이 등장한다.
가볍게 말하면 Spring 과 Database 사이에 Entity를 관리하는 영역이 있고, 그 영역에서 entity의 값이 바뀌면 물고 있다가 commit 이 일어나면 Database 로 변경된 값으로 저장하는 것이다.
@Transactional
service 클래스에서는 필수적으로 사용되고, 메소드 단위로 사용된다.
가볍게 말하면 이 녀석의 역할은 Transaction 을 시작(begin), 종료(commit), 예외(rollback) 처리해준다.
위에 update() 와 같이 Transaction 이 오류 없이 완료되면 commit 이 되기 때문에 Database 의 값이 변경된다고 생각하면 될 것 같다.
5. Controller 생성
package com.mkdevlab.springbootboard.controller;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
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;
import com.mkdevlab.springbootboard.dto.BoardRequestDto;
import com.mkdevlab.springbootboard.dto.BoardResponseDto;
import com.mkdevlab.springbootboard.service.BoardService;
import lombok.RequiredArgsConstructor;
@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
public class BoardRestController {
private final BoardService service;
@PostMapping("/boards")
public Long save(@RequestBody BoardRequestDto param) {
return service.save(param);
}
@GetMapping("/boards")
public List<BoardResponseDto> findAll(){
return service.findAll();
}
@PatchMapping("/boards/{id}")
public Long save(@PathVariable Long id, @RequestBody BoardRequestDto param) throws Exception {
return service.update(id, param);
}
}
Advanced Rest client 를 사용해서 잘 작동하는 지 확인해보자.
1. 게시글 등록
7 이라는 숫자가 찍힌 걸 볼 수 있다. PK 로 지정했던 id 의 값이다. 이제 DB 에 저장되었는 지 확인해보자.
잘 저장 되었다!
2. 게시글 조회 (findAll())
리스트로 잘 나온다!
3. 게시글 수정
제목을 수정하고 SEND를 누르자 7 이라는 숫자로 Return 온 것을 확인하였다. 실제 DB를 조회해보자.
title 이 바뀐걸 볼 수 있고, modified_date 가 update 된 걸 볼 수 있다.
이것으로 게시글 CRUD 를 모두 살펴보았다.
이렇게 아주 간단하게 backend 영역을 살펴보았다.
다음에는 frontend 영역으로 이동해서 게시판 화면을 만들어보도록 하자!
끝.
Reference
https://congsong.tistory.com/55?category=749196
'개발이야기 > Spring Boot' 카테고리의 다른 글
Spring Boot JPA 게시판 - CRUD (with MySQL) (0) | 2022.04.11 |
---|---|
Spring Security (0) | 2022.04.10 |
ORM (0) | 2022.04.03 |