feat(shop): 实现商品销量累加和跨租户查询功能
- 添加商品销量累加功能,确保支付成功后更新销量- 实现跨租户查询用户和订单商品的功能 - 修复支付回调中的错误代码 -优化日志记录和异常处理
This commit is contained in:
235
docs/商品销量累加功能实现.md
Normal file
235
docs/商品销量累加功能实现.md
Normal file
@@ -0,0 +1,235 @@
|
||||
# 商品销量累加功能实现
|
||||
|
||||
## 🎯 功能概述
|
||||
|
||||
实现了商品销售数量的累加功能,确保在支付成功后能够正确更新商品的销量统计。使用`@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] 添加详细的日志记录
|
||||
|
||||
## 🎉 总结
|
||||
|
||||
商品销量累加功能已完整实现,具备以下特性:
|
||||
- **可靠性**: 忽略租户隔离,确保更新成功
|
||||
- **一致性**: 原子性操作,避免并发问题
|
||||
- **健壮性**: 完善的错误处理和参数验证
|
||||
- **可观测性**: 详细的日志记录和监控
|
||||
- **可测试性**: 完整的测试用例覆盖
|
||||
|
||||
现在支付成功后,商品销量能够正确累加,不会因为租户隔离或其他问题导致更新失败。
|
||||
Reference in New Issue
Block a user