小程序开发-服务端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

7.1 KiB

商品销量累加功能实现

🎯 功能概述

实现了商品销售数量的累加功能,确保在支付成功后能够正确更新商品的销量统计。使用@InterceptorIgnore注解忽略租户隔离,确保跨租户的商品销量能够正确更新。

🔧 实现内容

1. ShopGoodsService接口扩展

文件: src/main/java/com/gxwebsoft/shop/service/ShopGoodsService.java

/**
 * 累加商品销售数量
 * 忽略租户隔离,确保能更新成功
 *
 * @param goodsId 商品ID
 * @param saleCount 累加的销售数量
 * @return 是否更新成功
 */
boolean addSaleCount(Integer goodsId, Integer saleCount);

2. ShopGoodsMapper数据库操作

文件: src/main/java/com/gxwebsoft/shop/mapper/ShopGoodsMapper.java

/**
 * 累加商品销售数量
 * 使用@InterceptorIgnore忽略租户隔离,确保能更新成功
 *
 * @param goodsId 商品ID
 * @param saleCount 累加的销售数量
 * @return 影响的行数
 */
@InterceptorIgnore(tenantLine = "true")
@Update("UPDATE shop_goods SET sales = IFNULL(sales, 0) + #{saleCount} WHERE goods_id = #{goodsId}")
int addSaleCount(@Param("goodsId") Integer goodsId, @Param("saleCount") Integer saleCount);

关键特性:

  • @InterceptorIgnore(tenantLine = "true") - 忽略租户隔离
  • IFNULL(sales, 0) - 处理销量字段为null的情况
  • 原子性操作 - 直接在数据库层面进行累加

3. ShopGoodsServiceImpl业务实现

文件: src/main/java/com/gxwebsoft/shop/service/impl/ShopGoodsServiceImpl.java

@Override
public boolean addSaleCount(Integer goodsId, Integer saleCount) {
    try {
        if (goodsId == null || saleCount == null || saleCount <= 0) {
            log.warn("累加商品销量参数无效 - 商品ID: {}, 销量: {}", goodsId, saleCount);
            return false;
        }

        int affectedRows = baseMapper.addSaleCount(goodsId, saleCount);
        boolean success = affectedRows > 0;
        
        if (success) {
            log.info("商品销量累加成功 - 商品ID: {}, 累加数量: {}, 影响行数: {}", goodsId, saleCount, affectedRows);
        } else {
            log.warn("商品销量累加失败 - 商品ID: {}, 累加数量: {}, 影响行数: {}", goodsId, saleCount, affectedRows);
        }
        
        return success;
    } catch (Exception e) {
        log.error("累加商品销量异常 - 商品ID: {}, 累加数量: {}", goodsId, saleCount, e);
        return false;
    }
}

功能特性:

  • 参数验证 - 检查goodsId和saleCount的有效性
  • 异常处理 - 捕获并记录异常信息
  • 详细日志 - 记录操作结果和关键信息
  • 返回值明确 - 明确返回操作是否成功

4. ShopOrderServiceImpl集成

文件: src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java

/**
 * 累计单个商品的销量
 * 使用新的addSaleCount方法,忽略租户隔离确保更新成功
 */
private void updateSingleGoodsSales(ShopOrderGoods orderGoods) {
    try {
        if (orderGoods.getGoodsId() == null || orderGoods.getTotalNum() == null || orderGoods.getTotalNum() <= 0) {
            log.warn("商品销量累计参数无效 - 商品ID:{},购买数量:{}", 
                orderGoods.getGoodsId(), orderGoods.getTotalNum());
            return;
        }

        // 使用新的addSaleCount方法,忽略租户隔离
        boolean updated = shopGoodsService.addSaleCount(orderGoods.getGoodsId(), orderGoods.getTotalNum());
        
        if (updated) {
            log.info("商品销量累计成功 - 商品ID:{},商品名称:{},购买数量:{}",
                orderGoods.getGoodsId(), orderGoods.getGoodsName(), orderGoods.getTotalNum());
        } else {
            log.warn("商品销量累计失败 - 商品ID:{},商品名称:{},购买数量:{}",
                orderGoods.getGoodsId(), orderGoods.getGoodsName(), orderGoods.getTotalNum());
        }
    } catch (Exception e) {
        log.error("累计单个商品销量异常 - 商品ID:{},商品名称:{},购买数量:{}",
            orderGoods.getGoodsId(), orderGoods.getGoodsName(), orderGoods.getTotalNum(), e);
    }
}

🔄 调用流程

支付成功回调
    ↓
ShopOrderServiceImpl.updateByOutTradeNo()
    ↓
handlePaymentSuccess()
    ↓
updateGoodsSales()
    ↓
updateSingleGoodsSales()
    ↓
ShopGoodsService.addSaleCount()
    ↓
ShopGoodsMapper.addSaleCount() [忽略租户隔离]
    ↓
数据库更新销量

🎯 核心优势

1. 租户隔离处理

  • 使用@InterceptorIgnore(tenantLine = "true")忽略租户隔离
  • 确保跨租户商品销量能够正确更新
  • 避免因租户隔离导致的更新失败

2. 数据一致性

  • 原子性操作 - 在数据库层面直接累加
  • 避免并发问题 - 不需要先查询再更新
  • 处理null值 - 使用IFNULL确保计算正确

3. 错误处理

  • 完善的参数验证
  • 异常捕获和日志记录
  • 明确的返回值指示操作结果

4. 性能优化

  • 单条SQL语句完成累加
  • 避免查询-修改-更新的多步操作
  • 减少数据库交互次数

🧪 测试验证

测试文件: src/test/java/com/gxwebsoft/shop/service/ShopGoodsSalesTest.java

测试用例

  1. 基本功能测试 - 验证正常的销量累加
  2. 参数验证测试 - 验证各种无效参数的处理
  3. 批量累加测试 - 验证多次累加的正确性

运行测试

# 运行单个测试类
mvn test -Dtest=ShopGoodsSalesTest

# 运行特定测试方法
mvn test -Dtest=ShopGoodsSalesTest#testAddSaleCount

📋 使用示例

// 在支付成功后累加商品销量
@Resource
private ShopGoodsService shopGoodsService;

// 累加销量
Integer goodsId = 123;
Integer purchaseCount = 5;
boolean success = shopGoodsService.addSaleCount(goodsId, purchaseCount);

if (success) {
    log.info("商品销量累加成功");
} else {
    log.error("商品销量累加失败");
}

🔍 监控和日志

成功日志

商品销量累加成功 - 商品ID: 123, 累加数量: 5, 影响行数: 1

失败日志

商品销量累加失败 - 商品ID: 123, 累加数量: 5, 影响行数: 0
累加商品销量参数无效 - 商品ID: null, 销量: 5

异常日志

累加商品销量异常 - 商品ID: 123, 累加数量: 5

验证清单

  • ShopGoodsService接口添加addSaleCount方法
  • ShopGoodsMapper添加数据库操作方法
  • 使用@InterceptorIgnore忽略租户隔离
  • ShopGoodsServiceImpl实现业务逻辑
  • ShopOrderServiceImpl集成新方法
  • 添加完善的参数验证和异常处理
  • 创建测试用例验证功能
  • 添加详细的日志记录

🎉 总结

商品销量累加功能已完整实现,具备以下特性:

  • 可靠性: 忽略租户隔离,确保更新成功
  • 一致性: 原子性操作,避免并发问题
  • 健壮性: 完善的错误处理和参数验证
  • 可观测性: 详细的日志记录和监控
  • 可测试性: 完整的测试用例覆盖

现在支付成功后,商品销量能够正确累加,不会因为租户隔离或其他问题导致更新失败。