Spring Boot实现按itemcode批量扣减库存并校验itemcode有效性
实现方案
你现有代码首先存在核心逻辑错误:当前Repository层是直接把请求传入的stock值直接覆盖数据库原有库存,不符合「原有库存扣减对应数值」的需求,需要先修正,再补充存在性校验逻辑。
1. 修正Repository层代码
新增批量查询存在的itemCode方法,同时调整库存更新逻辑为扣减模式:
// 批量查询数据库中已存在的itemCode列表 @Query("SELECT i.itemCode FROM Items i WHERE i.itemCode IN :itemCodes") List<Integer> findExistingItemCodes(@Param("itemCodes") List<Integer> itemCodes); // 修正为库存扣减逻辑,返回值为更新影响的行数 @Modifying @Query("UPDATE Items i SET i.stock = i.stock - :deductNum, i.updatedDate = :date WHERE i.itemCode = :itemCode") int deductStockByItemCode(@Param("itemCode") Integer itemCode, @Param("deductNum") Integer deductNum, @Param("date") LocalDateTime date);
注:去掉Repository层的@Transactional注解,统一移到Service层管理事务,保证操作原子性
2. Service层完整逻辑
Service层需要做参数校验、存在性校验、库存扣减全流程控制,同时添加事务保证所有操作要么全部成功要么全部回滚:
@Override @Transactional(rollbackFor = Exception.class) public ResponseEntity<?> updateMultipleStockByitemCode(List<Items> items) { // 第一步:基础参数合法性校验 List<Integer> requestItemCodes = items.stream() .peek(item -> { if (item.getItemCode() == null || item.getStock() == null || item.getStock() <= 0) { throw new IllegalArgumentException("参数非法:itemCode和扣减数量不能为空,且扣减数量必须大于0"); } }) .map(Items::getItemCode) .collect(Collectors.toList()); // 第二步:批量查询数据库中存在的itemCode,避免循环查询降低性能 List<Integer> existingItemCodes = repository.findExistingItemCodes(requestItemCodes); // 第三步:校验是否有不存在的itemCode,有则直接返回错误不执行扣减 List<Integer> notExistCodes = requestItemCodes.stream() .filter(code -> !existingItemCodes.contains(code)) .collect(Collectors.toList()); if (!notExistCodes.isEmpty()) { return ResponseEntity.badRequest().body("扣减失败,以下itemCode不存在:" + notExistCodes); } // 第四步:执行库存扣减,可根据业务需求补充库存不足校验,避免负库存 LocalDateTime updateTime = LocalDateTime.now(); for (Items item : items) { int affectRows = repository.deductStockByItemCode(item.getItemCode(), item.getStock(), updateTime); if (affectRows == 0) { throw new RuntimeException("itemCode为" + item.getItemCode() + "的商品扣减失败,请重试"); } } return ResponseEntity.ok("批量库存扣减成功"); }
3. 可选优化建议
- 如果并发请求量高,可以给商品表加
version乐观锁字段,避免超卖问题 - 如果单次批量扣减的商品数量超过100条,建议换成MyBatis批量更新语法,比循环单条更新性能高3倍以上
内容的提问来源于stack exchange,提问作者user15958535
相关产品推荐
相关产品推荐

