# 商品销量累加功能实现 ## 🎯 功能概述 实现了商品销售数量的累加功能,确保在支付成功后能够正确更新商品的销量统计。使用`@InterceptorIgnore`注解忽略租户隔离,确保跨租户的商品销量能够正确更新。 ## 🔧 实现内容 ### 1. ShopGoodsService接口扩展 **文件**: `src/main/java/com/gxwebsoft/shop/service/ShopGoodsService.java` ```java /** * 累加商品销售数量 * 忽略租户隔离,确保能更新成功 * * @param goodsId 商品ID * @param saleCount 累加的销售数量 * @return 是否更新成功 */ boolean addSaleCount(Integer goodsId, Integer saleCount); ``` ### 2. ShopGoodsMapper数据库操作 **文件**: `src/main/java/com/gxwebsoft/shop/mapper/ShopGoodsMapper.java` ```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` ```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` ```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. **批量累加测试** - 验证多次累加的正确性 ### 运行测试 ```bash # 运行单个测试类 mvn test -Dtest=ShopGoodsSalesTest # 运行特定测试方法 mvn test -Dtest=ShopGoodsSalesTest#testAddSaleCount ``` ## 📋 使用示例 ```java // 在支付成功后累加商品销量 @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 ``` ## ✅ 验证清单 - [x] ShopGoodsService接口添加addSaleCount方法 - [x] ShopGoodsMapper添加数据库操作方法 - [x] 使用@InterceptorIgnore忽略租户隔离 - [x] ShopGoodsServiceImpl实现业务逻辑 - [x] ShopOrderServiceImpl集成新方法 - [x] 添加完善的参数验证和异常处理 - [x] 创建测试用例验证功能 - [x] 添加详细的日志记录 ## 🎉 总结 商品销量累加功能已完整实现,具备以下特性: - **可靠性**: 忽略租户隔离,确保更新成功 - **一致性**: 原子性操作,避免并发问题 - **健壮性**: 完善的错误处理和参数验证 - **可观测性**: 详细的日志记录和监控 - **可测试性**: 完整的测试用例覆盖 现在支付成功后,商品销量能够正确累加,不会因为租户隔离或其他问题导致更新失败。