이번 방학에 멘토링을 통해 스프링을 배우게 시작하였다.
처음 배우다 보니 아직 어려운 부분이 있는다는 생각을 하였다.
따라서 복습 및 개인 공부를 위해 기록하기로 하였다.
CRUD는 Create, Read, Update, Delete의 약자이다.
이번에 매우 간단하게 CRUD 게시판 틀을 만들어봤다.
가장 중요한 파일 구조 및 JPA
Reposioty
- JPA를 이용해서 데이터베이스의 데이터를 가져온다.
Entity
- JPA를 이용해서 테이블 생성 및, 데이터를 다룰 수 있다.
Service
- 기능 구현 담당, Repository를 불러와서 기능을 구현하거나, 데이터를 저장한다
Controller
- 클라이언트와 직접적으로 통신하며, Service를 불러서 기능 구현을 명령한다.
클라이언트(프런트엔드, 사용자)
- Controller에게 데이터 조회를 요청하거나, 데이터 저장을 명령한다.
JPA
- 애플리케이션과 데이터베이스의 테이블을 연결한다.
- 기술적으로 애플리케이션의 객체를 테이블에 자동 영속화해준다.
패키지 entity - 클래스 Board
package com.example.mentoring.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
/**
* Entity 는 데이터베이스 테이블이라고 보면 됩니다.
* Entity를 만들고 실행한 후, 데이터베이스를 확인해보면 아래 코드대로 테이블이 생성된 걸 볼 수 있습니다.
*/
@Data // Getter + Setter
@AllArgsConstructor //모든 인스턴스를 받는 생성자
@NoArgsConstructor //기본 생성자
@Entity // 얘가 있어야지 스프링이 Board Entity 인식함
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) //인스턴스를 생성하면, 자동으로 인덱스를 붙여라
private int id; //1,2,3,4,5 테이블에서 구별하기위한 Index
@Column(nullable = false, length = 30) // null값 허용 안됨, 길이 제한 30자 이내
private String title;
@Column(nullable = false)
private String content;
@Column(nullable = false)
private String writer;
public Board(String title, String content, String writer) {
this.title = title;
this.content = content;
this.writer = writer;
}
}
패키지 repository - 인터페이스 BoardRepository
package com.example.mentoring.repository;
import com.example.mentoring.entity.Board;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* Repository 는 JPA를 이용해서 데이터베이스에서 데이터를 불러오거나 저장하는 용도입니다.
* Repository는 Service 클래스에서 기능 구현할 때 사용합니다.
*
* @Repository 는 생략해도됨, 이유는 인터페이스가 JpaRepository 상속 받는데 안에 @Repository가 포함됨
*/
@Repository
public interface BoardRepository extends JpaRepository <Board, Integer> {
}
패키지 service - 클래스 BoardService
package com.example.mentoring.service;
import com.example.mentoring.entity.Board;
import com.example.mentoring.repository.BoardRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* Service 는 기능을 구현하는 것에 초점을 둔 클래스입니다.
* Repository 를 불러와서, 데이터베이스에 데이터를 넣거나 혹은 가져와서 기능을 구현합니다.
* <p>
* Service 클래스는 Controller 에서 불러와서 사용합니다.
*/
@RequiredArgsConstructor //@Non null+ static 생성자
@Service
public class BoardService {
private final BoardRepository boardRepository;
// 게시글 전체 조회
//List는 배열느낌 List로 한번에 묶어서 보내기위해 사용
@Transactional(readOnly = true) //불러오기만할거임, 수정x readOnly = true(단순조회)
public List<Board> findAllBoard(){
List<Board> boards = boardRepository.findAll();
return boards;
}
// == return boardRepository.findAll();
// 게시글 단건 조회, 예외처리해야함
@Transactional(readOnly = true)
public Board findBoard(int id) {
return boardRepository.findById(id).orElseThrow(IllegalArgumentException::new);
}
// 게시글 작성
@Transactional
public Board writeBoard(Board boardReq) {
Board board = new Board(boardReq.getTitle(), boardReq.getContent(), boardReq.getWriter());
boardRepository.save(board);
return board;
}
//제목,내용... 통으로 보내줌.보내준거 다시 리턴해준다.
// 게시글 수정
@Transactional //모든 작업을 성공적으로 수행했을때만 작업함,1개라도 오류시 전부 취소
//을 붙이면 더티체킹이 일어나서, 저장하지 않아도 메서드가 성공적으로 끝나면 저장
public Board editBoard(int id, Board updateBoard) {
//기존게시물을 꺼내옴
Board board = boardRepository.findById(id).orElseThrow(() -> {
return new IllegalArgumentException();
});
//기존 게시물에 update 정보를 덮어씌움
board.setTitle(updateBoard.getTitle());
board.setContent(updateBoard.getContent());
return board;
}
// 게시글 삭제
@Transactional
public void deleteBoard(int id) {
Board board = boardRepository.findById(id).orElseThrow(() -> {
return new IllegalArgumentException();
});
boardRepository.deleteById(id);
}
}
패키지 controller - 클래스 BoardController
package com.example.mentoring.controller;
import com.example.mentoring.entity.Board;
import com.example.mentoring.service.BoardService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
/**
* Controller 는 클라이언트(사용자)의 요청을 받는 클래스입니다.
* Controller에서는 서비스 클래스 (기능 구현된 클래스) 를 불러서 사용자의 요청을 처리합니다.
*
* @Controller 는 템플릿 엔진(JSP, Thymeleaf 등등) 사용할 때 주로 쓰이고,
* @RestController 는 API 서버를 만들 때 주로 사용됩니다. 저희는 API 서버를 만드니 RestController 로 진행합니다.
*/
@RequiredArgsConstructor // 생성자
@RestController
public class BoardController {
private final BoardService boardService;
// 게시글 전체 조회
@GetMapping("/api/boards")
public ResponseEntity<?> findAll() {
return new ResponseEntity<>(boardService.findAllBoard(), HttpStatus.OK);
}
//ResponseEntity => Data+HTTP 상태코드 성공 200 OK, 오류시404..등등
// 게시글 단건 조회
@GetMapping("/api/boards/{id}")
public ResponseEntity<?> findBoard(@PathVariable("id") int id) {
return new ResponseEntity<>(boardService.findBoard(id), HttpStatus.OK);
}
// 게시글 작성
//*사용자가 게시글 작성->작성 완료 버튼 ->매개변수로 게시글이 들어옴->*들어온 게시글을 DB에 저장.
//매개변수로 게시글이 들어오면, ENTITY로 전송, HttpStatus.0K==200,HttpStatus.CREATED==201
//@RequestBody = JSON타입으로 데이터가 들어옴. 이걸 자바에서 인식할수있게 자바클래스로 매핑.
@PostMapping("/api/boards")
public ResponseEntity<?> writeBoard(@RequestBody Board board) {
return new ResponseEntity<>(boardService.writeBoard(board), HttpStatus.CREATED);
}
// 게시글 수정
//게시글 수정하고 완료버튼 누름 ->백엔드 서버 요청(id,updateBoard)
@PutMapping("/api/boards/{id}")
public ResponseEntity<?> editBoard(@PathVariable("id") int id, @RequestBody Board board) {
return new ResponseEntity<>(boardService.editBoard(id, board), HttpStatus.OK);
}
// 게시글 삭제
@DeleteMapping("/api/boards/{id}")
public ResponseEntity<?> deleteBoard(@PathVariable("id") int id) {
boardService.deleteBoard(id);
return new ResponseEntity<>("게시글 삭제 완료", HttpStatus.OK);
}
}
'활동' 카테고리의 다른 글
우아한테크코스 5기 - 2주차 후기 (0) | 2022.11.08 |
---|---|
교내 SW 프로그램 경진 대회 수상 및 후기 (1) | 2022.11.04 |
우아한테크코스 5기 - 1주차 후기 (2) | 2022.10.31 |
우아한테크코스5기 - 프리코스 시작전 다짐 (0) | 2022.10.26 |
[멘토링]스프링 Response만들기, 예외처리 추가 (0) | 2022.07.25 |