借书功能的实现思路
大约 2 分钟
v0: 能正常实现借书的操作
/**
* 借书
* @param bookDTO
* @return
*/
@Override
@Transactional
public boolean borrow(BookDTO bookDTO) {
Book book = bookMapper.getBookById(bookDTO.getBookId());
if (book.getNumber()-book.getStatus() > 0){
if (book.getNumber()-book.getStatus() >= bookDTO.getNumber()){
bookMapper.addStatus(bookDTO);
BookUser history = bookMapper.getHistory(bookDTO);
if (history != null){
bookDTO.setId(history.getId());
bookMapper.borrowHistory(bookDTO);
}else{
bookMapper.saveHistory(bookDTO);
}
return true;
}else{
return false;
}
}
return false;
}
V1: 悲观锁
获取图书信息时,使用了新的mapper层的获取图书信息方法:
/**
* 用于借书操作并锁定记录的方法
* @param id
*/
@Select("SELECT * FROM book WHERE id = #{id} FOR UPDATE")
Book getBookForBorrow(int id);
V2: 乐观锁
给book表新加了version字段,并在实体类的version字段添加@Version注解,修改了判断条件和更新方法
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BookDTO {
private Integer id;
private Integer userId;
private Integer bookId;
private int status;
private int number;
private long version;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
private Integer id;
private Integer uuid;
private String name;
private String category;
private int status;
private int number;
private String author;
private String publisher;
private String img;
private double price;
@TableField(fill = FieldFill.INSERT)//插入时填充字段
private LocalDateTime createdTime;
@TableField(fill = FieldFill.INSERT_UPDATE)//插入和更新时填充字段
private LocalDateTime updatedTime;
@Version
private long version;
}
/**
* 借书
* @param bookDTO
* @return
*/
@Override
@Transactional
public boolean borrow(BookDTO bookDTO) {
// 悲观锁
// Book book = bookMapper.getBookForBorrow(bookDTO.getBookId());
Book book = bookMapper.getBookById(bookDTO.getBookId());
if (book == null){
return false;
}
if (book.getNumber()-book.getStatus() > 0){
// 检查版本号是否一致,如果一致则准备更新
if (book.getVersion() == bookDTO.getVersion()) {
if (book.getNumber()-book.getStatus() >= bookDTO.getNumber()){
// 对图书表的操作
bookMapper.updateStatusAndVersion(bookDTO);
// 对借书记录表的操作
BookUser history = bookMapper.getHistory(bookDTO);
if (history != null){
bookDTO.setId(history.getId());
bookMapper.borrowHistory(bookDTO);
}else{
bookMapper.saveHistory(bookDTO);
}
return true;
}else{
return false;
}
} else {
// 版本号不一致,表示数据已经被其他事务修改,需要抛出异常或返回错误信息
throw new OptimisticLockingFailureException("图书数据已被其他事务修改,请稍后重试");
}
}
return false;
}
/**
* 增加图书的借书数量
* @param bookDTO
*/
@Update("UPDATE book SET status = book.status + #{number}, version = version + 1 WHERE id = #{bookId}")
void updateStatusAndVersion(BookDTO bookDTO);