You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 07:27:04