전 게시글은 아래를 참고 해주세요.

 

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

+ Recent posts