티스토리 뷰
[요구 사항]
- 사용자가 책을 반납할 수 있다.
[API 스펙]
- HTTP Method : PUT
- HTTP Path : /book/return
- HTTP Body(JSON) : {
"userName" : String,
"bookName" : String
}
- 결과 반환 X, HTTP Code 200이면 OK
- 대출(/book/loan)과 반납(/book/return)을 위한 HTTP Body(DTO)가 완전히 동일하다.
- 이때 반납을 위한 DTO를 새로 만드는게 좋을까? or 재활용하는게 좋을까?
cf) 대출을 위한 DTO(BookLoanRequest)는 이전 글에서 이미 만들어져 있는 상태
- 이 경우 강사는 (개인적으로) 새로 만드는 것을 선호한다.
- why? 나중에 대출과 반납 중 한 기능에 변화가 생겼을 때 유연하게 대처할 수 있기 때문이다.
1. 반납을 위한 Table은 따로 만들 필요 없다.(user_loan_history table 그대로 사용)
2. BookRetuenRequest(DTO)
package com.group.libraryapp.dto.book.request;
public class BookRetuenRequest {
private String bookName;
private String userName;
public String getBookName() {
return bookName;
}
public String getUserName() {
return userName;
}
}
3. Controller, Service
Controller
@RestController
public class BookController {
private final BookService bookService;
@PutMapping("/book/return")
public void returnBook(@RequestBody BookRetuenRequest request) {
bookService.returnBook(request);
}
}
Service
@Service
public class BookService {
private final BookRepository bookRepository;
private final UserLoanHistoryRepository userLoanHistoryRepository;
private final UserRepository userRepository;
// 생성자를 만들어 Spring bean을 주입받는다.
public BookService(BookRepository bookRepository,
UserLoanHistoryRepository userLoanHistoryRepository,
UserRepository userRepository
) {
this.bookRepository = bookRepository;
this.userLoanHistoryRepository = userLoanHistoryRepository;
this.userRepository = userRepository;
}
@Transactional
public void returnBook(BookRetuenRequest request) {
// 1. User table에서 User 정보를 가져온다.
User user = userRepository.findByName(request.getUserName())
.orElseThrow(IllegalArgumentException::new);
// 2. 유저의 ID와 책 이름을 이용해 대출 기록을 가져온다.
UserLoanHistory userLoanHistory = userLoanHistoryRepository
.findByUserIdAndBookName(user.getId(), request.getBookName())
.orElseThrow(IllegalArgumentException::new);
// 3. 반납 처리
userLoanHistory.doReturn();
// 4. user_loan_history 테이블의 IS_RETURN 컬럼 업데이트
// 영속성 컨텍스트의 '변경 감지' 기능으로 인해 별도의 코드나 쿼리를 작성할 필요가 없다.(그래서 아래 코드 주석 처리)
// by @Transactional Annotation
// userLoanHistoryRepository.save(userLoanHistory);
}
}
- UserLoanHistory에 doReturn method 추가
package com.group.libraryapp.domain.user.loanhistory;
import javax.persistence.*;
@Entity
public class UserLoanHistory {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id = null;
@Column(nullable = false, name = "user_id")
private long userId;
@Column(nullable = false, name = "book_name")
private String bookName;
@Column(nullable = false, name = "is_return")
// is_return 컬럼은 자료형이 tinyint이기 때문에 DB에 0(false) 혹은 1(true)이 들어가도 된다.
// == boolean으로 처리해도 tinyint에 잘 매핑된다.
private boolean isReturn;
protected UserLoanHistory() {}
public UserLoanHistory(long userId, String bookName, boolean isReturn) {
this.userId = userId;
this.bookName = bookName;
this.isReturn = isReturn;
}
public boolean getIsReturn() {
return isReturn;
}
// 반납 처리
public void doReturn() {
this.isReturn = true;
}
}
cf) userLoanHistoryRepository.save(userLoanHistory)를 주석 처리한 이유
2023.09.28 - [Spring] - #27 영속성 컨텍스트
#27 영속성 컨텍스트
- Service 계층의 주요 역할 중 하나가 트랜잭션을 관리하는 것이다. @Transactional - Spring에서 트랜잭션을 적용하는 방법 - 메소드에 @Transactional Annotation이 붙으면 메소드가 시작될 때 트랜잭션을 시
radderveloper.tistory.com
● 테스트
- user_loan_history table 현재 상황(0 = 대출 중 / 1 = 반납 완료) / user table 현재 상황
[현재 대출 상황]
손승완 - 주먹을 단련하는 법
배주현 - 하체를 단련하는 법
'Backend > Spring' 카테고리의 다른 글
#29 대출 기능 API (1) | 2023.10.07 |
---|---|
#28 책 생성 API - INSERT (1) | 2023.10.02 |
#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
- Java8
- Stream
- Spring Boot
- git
- SQL
- node.js
- 코테
- db
- DART
- 코딩테스트
- 프로세스
- 알고리즘
- jpa
- nosql
- java
- 메모리
- 운영체제
- Phaser3
- Phaser
- MySQL
- 빅데이터 분석기사
- API
- Advanced Stream
- 빅데이터
- SpringBoot
- 자료구조
- MongoDB
- 프로그래머스
- OS
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |