LendService
// book_Tb -> 대여상태 false, 대여수 -1
// lend_tb -> 반납한 일자 (now), 반납상태 -> true
@Transactional
public LendResponse.ReturnDTO 직접반납하기(Long userId, LendRequest.ReturnDTO request) {
// 1. 대여상태인지 확인
Boolean b = bookRepository.mCheckLendStatus(request.getIsbn13()).orElseThrow(() -> new ExceptionApi404("요청하신 도서가 존재하지 않습니다."));
if (!b) {
throw new ExceptionApi404("대여중인 도서가 아닙니다.");
}
// 2. booktb 대여 상태 바꾸기
int updateCount = bookRepository.mUpdateLendStatusAndCountReturn(request.getIsbn13());
// 업데이트가 성공했는지 확인 (1이 아니면 실패)
if (updateCount != 1) {
throw new ExceptionApi500("도서 반납 처리 중 문제가 발생했습니다.");
}
// 3.lend_tb 대여 상태 바꾸기
int returnStatus = lendRepository.mReturnLend(userId, request.getIsbn13());
// 업데이트 성공했는지 확인 (1이 아니면 실패)
if (returnStatus != 1) {
throw new ExceptionApi500("도서 반납 처리 중 문제가 발생했습니다.");
}
// 4. 반납정보 return
Lend lendPS = lendRepository.mFindLend(userId, request.getIsbn13());
return new LendResponse.ReturnDTO(lendPS);
}
→ 처음에 구현한 “도서반납하기” 기능의 서비스 레이어 코드.
마지막 4. 반납정보 return 부분의 mFindLend 의 쿼리는
LendRepository
// 해당 user와 book의 lend 데이터 조회
@Query("select l from Lend l where l.user.id = :userId AND l.book.isbn13 = :isbn13")
Lend mFindLend(@Param("userId") Long userId, @Param("isbn13") String isbn13);
이렇게 user_id와 isbn13(book의 pk)를 가지고 lend 데이터 조회하는 쿼리다.
→ 해당 유저가 여러번 해당 도서를 빌리고 반납했다면 lend_tb에 그 히스토리가 남기때문에 ( → return_status = false, true 로 반납된 도서인지 아닌지 구분하기 때문에 lend_tb에 대여한 도서 내역과 지금 대여중인 도서 내역이 전부다 들어가 있다. )
userId와 isbn13으로 조회하면 하나의 객체가 아니라 List가 출력될텐데
그 부분을 생각하지 못했다.

→ 기존에 빌린 내역이 없는 책은 이렇게 성공적으로 반납이 되어서 잘 되는줄 알았다.
하지만 기존에
9791190669238
이 도서를 빌린 내역이 있으면
{"reason": Query did not return a unique result: 2 results were returned}
이렇게 List로 받지 못해서 에러가 터진다.
→ 그래서 service 레이어 에서 반납정보를 찾아오는 쿼리를 수정했다.
LendRepository
// 가장 최근에 반납한 도서 1개를 select 하거라
@Query(value = "SELECT * FROM lend_tb WHERE user_id = :userId AND book_id = :isbn13 AND return_status = true ORDER BY return_date DESC LIMIT 1", nativeQuery = true)
Optional<Lend> findLatestReturnedLendNative(@Param("userId") Long userId, @Param("isbn13") String isbn13);
: 대여 내역중에 가장 최근에 반납한 ( = 방금 반납한 그 반납내역 ) 것만 select 하는 쿼리 !
ORDER BY return_date DESC LIMIT 1
를 추가해서 return_date를 내림차순으로 정렬해서 그 중 맨 윗단에 있는 1개 ( = 방금 반납한 그 반납내역 )를
지정하도록 했다.
LendService
// 5. 반납정보 return
Lend lendPS = lendRepository.findLatestReturnedLendNative(userId, request.getIsbn13())
.orElseThrow(() -> new ExceptionApi404("반납된 기록을 찾을 수 없습니다."));
방금 만든걸로 바꿔줬다.
LendService
// book_Tb -> 대여상태 false, 대여수 -1
// lend_tb -> 반납한 일자 (now), 반납상태 -> true
@Transactional
public LendResponse.ReturnDTO 직접반납하기(Long userId, LendRequest.ReturnDTO request) {
// 1. 대여상태인지 확인
Boolean b = bookRepository.mCheckLendStatus(request.getIsbn13()).orElseThrow(() -> new ExceptionApi404("요청하신 도서가 존재하지 않습니다."));
if (!b) {
throw new ExceptionApi404("대여중인 도서가 아닙니다.");
}
// 2. booktb 대여 상태 바꾸기
int updateCount = bookRepository.mUpdateLendStatusAndCountReturn(request.getIsbn13());
// 업데이트가 성공했는지 확인 (1이 아니면 실패)
if (updateCount != 1) {
throw new ExceptionApi500("book도서 반납 처리 중 문제가 발생했습니다.");
}
// 3.lend_tb 대여 상태 바꾸기
int returnStatus = lendRepository.mReturnLend(userId, request.getIsbn13());
// 업데이트 성공했는지 확인 (1이 아니면 실패)
if (returnStatus != 1) {
throw new ExceptionApi500("lend도서 반납 처리 중 문제가 발생했습니다.");
}
// 4. 반납 후 예약자가 있는지 확인하여 처리 - TODO: 신민재
boolean hasReservations = reservationRepository.countCurrentReservations(request.getIsbn13()) > 0;
if (hasReservations) {
// 첫 번째 예약자에게 자동 대여 처리
reservationService.자동대여(request.getIsbn13());
}
// 5. 반납정보 return
Lend lendPS = lendRepository.findLatestReturnedLendNative(userId, request.getIsbn13())
.orElseThrow(() -> new ExceptionApi404("반납된 기록을 찾을 수 없습니다."));
return new LendResponse.ReturnDTO(lendPS);
}
⇒ “반납 기능” 서비스 레이어 최종 코드
그리고 나서 기존
9791190669238
도서의 대여 내역을 여러개 만들고 이 있는 도서를 다시 빌린 후 반납해야하는 상황에서 반납하기를 요청하면

→ 반납이 잘 된다!
Share article