拿大学图书管理系统当例
实体类 需要有记录用户(包含管理员)操作的变量
package com.example.entity;
import java.io.Serializable;
/**
* 借阅管理表
*/
public class Borrow implements Serializable {
private static final long serialVersionUID = 1L;
/** 记录ID */
private Integer id;
/** 学生ID */
private Integer studentId;
/** 书籍ID */
private Integer booksId;
/** 借阅日期 */
private String borrowDate;
/** 归还日期 */
private String returnDate;
/** 借阅状态 */
private String status;
/** 审核状态 */
private String reviewStatus;
/** 审核理由 */
private String reason;
/** 学生姓名 */
private String studentName; //关联查询用
/** 书籍名 */
private String bookName; //关联查询用
/** 学生的操作类型 */
private String operation; //需要有记录用户(包含管理员)操作的变量
/** 书籍封面 */
private String booksCover; //关联查询用
}
在Service层的新增里实现借阅功能,写一个辅助新增查看该学生是否已经借阅的方法。 (代码量多,归还在下面)
public void add(Borrow borrow) {
Account currentUser = TokenUtils.getCurrentUser();
// 查看该学生是否已经借阅
List<Borrow> existingBorrowList = this.selectByBorrowIdAndStudentId(borrow.getBooksId(), currentUser.getId(),
borrow.getStatus());
if (existingBorrowList != null && !existingBorrowList.isEmpty()) {
// 找到最新的借阅记录
Borrow latestBorrow = existingBorrowList.stream()
.max(Comparator.comparing(Borrow::getBorrowDate)) // 假设Borrow对象有getBorrowDate方法
.orElse(null);
if (latestBorrow != null) {
if (latestBorrow.getStatus().equals(Constants.RETURNED)
|| latestBorrow.getStatus().equals(Constants.BORROWING_FAILED)) {
processBorrowRequest(borrow, currentUser);
} else {
throw new CustomException(ResultCodeEnum.BOOKS_BORROW_ERROR);
}
}
} else {
processBorrowRequest(borrow, currentUser);
}
}
/**
* 辅助新增查看该学生是否已经借阅
*/
public List<Borrow> selectByBorrowIdAndStudentId(Integer booksId, Integer studentId, String status) {
return borrowMapper.selectByBorrowIdAndStudentId(booksId, studentId, status);
}
/**
* 封装借阅功能,降低代码重复率
*/
private void processBorrowRequest(Borrow borrow, Account currentUser) {
// 更新书籍的可借副本数量
if (booksMapper.decrementCopies(borrow.getBooksId()) > 0) {
borrow.setStudentId(currentUser.getId());
borrow.setBorrowDate(DateUtil.now());
// 根据借阅日期计算归还日期并设置
DateTime returnDateTime = DateUtil.offsetDay(DateUtil.parse(borrow.getBorrowDate()), 30);
borrow.setReturnDate(DateUtil.formatDateTime(returnDateTime));
if (borrow.getOperation().equals(Constants.BORROWED)) {
borrow.setStatus(Constants.BORROWING_REVIEW_IN_PROGRESS);
borrow.setReviewStatus(Constants.PENDING_REVIEW);
}
borrowMapper.insert(borrow);
} else {
throw new CustomException(ResultCodeEnum.BOOKS_COPIES_ERROR);
}
}
单独写辅助新增查看该学生是否已经借阅的方法的Mapper层里的SQL代码,就有这一个单独写的方法,其他CRUD忽略没写
@Select("select * from borrow where books_id = #{booksId} and student_id = #{studentId} and status <> '已归还'")
List<Borrow> selectByBorrowIdAndStudentId(Integer booksId, Integer studentId, String status);
在Service层的修改里实现续借、归还、审核功能。 因为逻辑有点复杂,使用if-else的话(如果喜欢用if-else的话,代码我放在下面,就是有点丑),不容易维护,可读性差,所以我用了switch case 方法
public void updateById(Borrow borrow) {
switch (borrow.getOperation()) {
case Constants.ADOPT:
handleAdoptOperation(borrow);
break;
case Constants.REFUSE:
handleRefuseOperation(borrow);
break;
case Constants.CONTINUE_BORROWING:
handleContinueBorrowingOperation(borrow);
break;
case Constants.RETURN:
handleReturnOperation(borrow);
break;
}
borrowMapper.updateById(borrow);
}
private void handleAdoptOperation(Borrow borrow) {
switch (borrow.getStatus()) {
case Constants.BORROWING_REVIEW_IN_PROGRESS:
borrow.setStatus(Constants.BORROWING);
borrow.setReviewStatus(Constants.ADOPT);
break;
case Constants.RENEWAL_REVIEW_IN_PROGRESS:
borrow.setStatus(Constants.RENEWAL);
borrow.setReviewStatus(Constants.ADOPT);
setRenewalReturnDate(borrow);
break;
case Constants.RETURNED_REVIEW_IN_PROGRESS:
borrow.setStatus(Constants.RETURNED);
borrow.setReviewStatus(Constants.ADOPT);
borrow.setReturnDate(DateUtil.now());
booksMapper.incrementCopies(borrow.getBooksId());
break;
}
}
private void handleRefuseOperation(Borrow borrow) {
switch (borrow.getStatus()) {
case Constants.RETURNED_REVIEW_IN_PROGRESS:
borrow.setStatus(Constants.RESTITUTION_FAILED);
borrow.setReviewStatus(Constants.REFUSE);
break;
case Constants.RENEWAL_REVIEW_IN_PROGRESS:
borrow.setStatus(Constants.RENEWAL_FAILED);
borrow.setReviewStatus(Constants.REFUSE);
break;
default:
borrow.setStatus(Constants.BORROWING_FAILED);
borrow.setReviewStatus(Constants.REFUSE);
booksMapper.incrementCopies(borrow.getBooksId());
break;
}
}
private void handleContinueBorrowingOperation(Borrow borrow) {
borrow.setStatus(Constants.RENEWAL_REVIEW_IN_PROGRESS);
borrow.setReviewStatus(Constants.PENDING_REVIEW);
}
private void handleReturnOperation(Borrow borrow) {
borrow.setStatus(Constants.RETURNED_REVIEW_IN_PROGRESS);
borrow.setReviewStatus(Constants.PENDING_REVIEW);
}
private void setRenewalReturnDate(Borrow borrow) {
DateTime returnDateTime = DateUtil.offsetDay(DateUtil.parse(borrow.getReturnDate()), 15);
borrow.setReturnDate(DateUtil.formatDateTime(returnDateTime));
}
在Service层的修改里使用if-else实现续借、归还、审核功能。
public void updateById(Borrow borrow) {
if (borrow.getOperation().equals(Constants.ADOPT)) {
if (borrow.getStatus().equals(Constants.BORROWING_REVIEW_IN_PROGRESS)) {
borrow.setStatus(Constants.BORROWING);
borrow.setReviewStatus(Constants.ADOPT);
} else if (borrow.getStatus().equals(Constants.RENEWAL_REVIEW_IN_PROGRESS)) {
borrow.setStatus(Constants.RENEWAL);
borrow.setReviewStatus(Constants.ADOPT);
// 根据借阅后的归还日期计算续借后的归还日期并设置
DateTime returnDateTime = DateUtil.offsetDay(DateUtil.parse(borrow.getReturnDate()), 15);
borrow.setReturnDate(DateUtil.formatDateTime(returnDateTime));
} else if (borrow.getStatus().equals(Constants.RETURNED_REVIEW_IN_PROGRESS)) {
borrow.setStatus(Constants.RETURNED);
borrow.setReviewStatus(Constants.ADOPT);
borrow.setReturnDate(DateUtil.now());
booksMapper.incrementCopies(borrow.getBooksId());
}
} else if (borrow.getOperation().equals(Constants.REFUSE)) {
if (borrow.getStatus().equals(Constants.RETURNED_REVIEW_IN_PROGRESS)) {
borrow.setStatus(Constants.RESTITUTION_FAILED);
borrow.setReviewStatus(Constants.REFUSE);
} else if (borrow.getStatus().equals(Constants.RENEWAL_REVIEW_IN_PROGRESS)) {
borrow.setStatus(Constants.RENEWAL_FAILED);
borrow.setReviewStatus(Constants.REFUSE);
} else {
borrow.setStatus(Constants.BORROWING_FAILED);
borrow.setReviewStatus(Constants.REFUSE);
booksMapper.incrementCopies(borrow.getBooksId());
}
} else if (borrow.getOperation().equals(Constants.CONTINUE_BORROWING)) {
borrow.setStatus(Constants.RENEWAL_REVIEW_IN_PROGRESS);
borrow.setReviewStatus(Constants.PENDING_REVIEW);
} else if (borrow.getOperation().equals(Constants.RETURN)) {
borrow.setStatus(Constants.RETURNED_REVIEW_IN_PROGRESS);
borrow.setReviewStatus(Constants.PENDING_REVIEW);
}
borrowMapper.updateById(borrow);
}
这是用数据库操作的方式实现借阅时书籍可借副本数量+1和归还时书籍可借副本数量-1,在books类的Mapper层里实现。这两在上面的修改里被调用(注意被调用时的方法名)
/**
* 数据库借阅书籍操作
*/
@Update("UPDATE books SET copies = copies - 1 WHERE id = #{bookId} AND copies > 0")
int decrementCopies(@Param("bookId") int bookId);
/**
* 数据库归还书籍操作
*/
@Update("UPDATE books SET copies = copies + 1 WHERE id = #{bookId}")
int incrementCopies(@Param("bookId") int bookId);
在新增和修改里用到的常量
package com.example.common;
public interface Constants {
String TOKEN = "xxxxx";
String STUDENT_DEFAULT_PASSWORD = "xxxxxx";
String BORROWING_REVIEW_IN_PROGRESS = "借阅审核中";
String BORROWING = "借阅中";
String BORROWING_FAILED = "借阅失败";
String RENEWAL_REVIEW_IN_PROGRESS = "续借审核中";
String RENEWAL_FAILED = "续借失败";
String RENEWAL = "续借中";
String RETURNED_REVIEW_IN_PROGRESS = "归还审核中";
String RESTITUTION_FAILED = "归还失败";
String RETURNED = "已归还";
String PENDING_REVIEW = "待审核";
String ADOPT = "通过";
String REFUSE = "拒绝";
String BORROWED = "借阅";
String CONTINUE_BORROWING = "续借";
String RETURN = "归还";
}
最后用普通人看得懂的话来讲一下,这一整套操作的逻辑和流程哈。
review_status 审核状态 , status 借阅状态
学生在自己的页面里点击借阅时review_status值为“待审核”,status值为“借阅审核中”。管理员在status值为“借阅审核中”时给用户审核通过后review_status值为“通过”,status值为“借阅中”,从可借副本数量-1。如果给用户审核“拒绝”review_status值为“拒绝”,status值为“借阅失败”,给可借副本数量+1。
用户点击续借时review_status值为“待审核”,status值为“续借审核中”。管理员在status值为“续借审核中”时给用户审核“通过”后review_status值为“通过”,status值为“续借中”。如果给用户审核“拒绝”review_status值为“拒绝”,status值为“续借失败”。
用户点击归还时review_status值为“待审核”,status值为“归还审核中”。管理员在status值为“归还审核中”时给用户审核“通过”就review_status值为“通过”,status值为“已归还”,给可借副本数量+1。