티스토리 뷰
- 다음 글 부터는 먼저 코드를 작성한 다음에 강의를 들어보자
● 도서관에 책을 등록하는 기능
[API 스펙]
- HTTP Method : POST
- HTTP Path : /book
- HTTP Body(JSON) : {"name" : String // 책 이름} → name은 필수
- 결과 반환 X, HTTP Code 200이면 OK
- 이러한 구조로 만들어야 한다.

1. Book Table
CREATE TABLE BOOK (
ID BIGINT AUTO_INCREMENT,
NAME VARCHAR(255) NOT NULL,
PRIMARY KEY(ID)
);
- VARCHAR(255)라고 설정한 이유
1. JPA를 사용할 때 @Column Annotation의 length 속성의 기본값이 255이다. → @Column Annotation에서 length 속성을 생략할려고 (255)로 설정한 것이다.
2. 문자열 필드의 경우 최적화를 해야 하는 CASE가 아니라면 조금 여유롭게 설정하는 것이 좋다.

2. Book 객체
package com.group.libraryapp.domain.book;
import javax.persistence.*;
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id = null;
@Column(nullable = false, name = "name")
private String name;
// JPA Entity는 기본 생성자가 하나 필요하다.
protected Book() {}
public Book(String name) {
// name은 필수값이다.
if(name == null || name.isBlank()) throw new IllegalArgumentException(String.format("잘못된 name(%s)이 들어왔습니다.", name));
this.name = name;
}
}

3. BookRepository
package com.group.libraryapp.domain.book;
import org.springframework.data.jpa.repository.JpaRepository;
public interface BookRepository extends JpaRepository<Book, Long> {
}

cf)

- 강의를 듣다보니 BookRepository와 UserRepository를 왜 하필 domain package 아래에 생성하는지 궁금했다. 그냥 Repository package 아래에 생성하면 통일성이 있는데 강사는 왜 그런 것일까?
- 아니나 다를까 이미 다른 사람이 이에 대해서 물어봤다.
- 강사의 답변을 보니 이건 그냥 강사 개인이 이번 Spring 강의에서 만드는 프로젝트는 이러한 구조가 더 적합한 것 같아서 그렇게 구성한 것이라고 한다.
- 패키지를 구성하는 방법에는 정답이 없고 상황에 따라 매번 달라진다.
4. DTO
- DTO는 HTTP Body 스펙을 보고 그에 맞게 생성하면 된다.
HTTP Body(JSON) : {"name" : String // 책 이름} → name은 필수
package com.group.libraryapp.dto.book.request;
public class BookCreateRequest {
private String name;
public String getName() {
return this.name;
}
}


5. Controller & Service
[Controller]
package com.group.libraryapp.controller.book;
import com.group.libraryapp.dto.book.request.BookCreateRequest;
import com.group.libraryapp.service.book.BookService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class BookController {
private final BookService bookService;
// 생성자를 만들어 Spring bean을 주입받는다.
public BookController(BookService bookService) {
this.bookService = bookService;
}
@PostMapping("/book")
public void saveBook(@RequestBody BookCreateRequest request) {
bookService.saveBook(request);
}
}
[Service]
package com.group.libraryapp.service.book;
import com.group.libraryapp.domain.book.Book;
import com.group.libraryapp.domain.user.BookRepository;
import com.group.libraryapp.dto.book.request.BookCreateRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class BookService {
private final BookRepository bookRepository;
// 생성자를 만들어 Spring bean을 주입받는다.
public BookService(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
@Transactional
public void saveBook(BookCreateRequest request) {
bookRepository.save(new Book(request.getName()));
}
}
cf)
2023.08.04 - [Spring] - #7 DTO와 VO(Entity는 링크한 글을 보자)
#7 DTO와 VO(Entity는 링크한 글을 보자)
DTO : 데이터 전달용 객체 / VO : 값 표현용 객체 DTO VO 용도 레이어 간 데이터 전달 값 그 자체 표현 동등 결정 속성값이 모두 같아도 동일한 객체 X 속성값이 모두 같으면 동일 객체 가변 / 불변 sette
radderveloper.tistory.com
● 테스트



'Backend > Spring' 카테고리의 다른 글
#30 반납 기능 (0) | 2023.10.09 |
---|---|
#29 대출 기능 API (1) | 2023.10.07 |
#27 영속성 컨텍스트 (1) | 2023.09.28 |
#26 JPA를 이용해 SQL 날리기 with Spring Data JPA2 (0) | 2023.09.26 |
#25 트랜잭션 - 이론 (0) | 2023.09.25 |
- Total
- Today
- Yesterday
- spring
- java
- API
- git
- 메모리
- 빅데이터 분석기사
- 프로세스
- 자료구조
- 운영체제
- DART
- nosql
- Phaser3
- node.js
- 프로그래머스
- MongoDB
- 알고리즘
- jpa
- Advanced Stream
- SQL
- 빅데이터
- MySQL
- 코딩테스트
- db
- 코테
- Phaser
- SpringBoot
- Spring Boot
- OS
- Stream
- Java8
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |