11
This commit is contained in:
239
docs/订单商品忽略租户隔离查询功能.md
Normal file
239
docs/订单商品忽略租户隔离查询功能.md
Normal file
@@ -0,0 +1,239 @@
|
||||
# 订单商品忽略租户隔离查询功能实现
|
||||
|
||||
## 🔍 问题背景
|
||||
|
||||
在支付回调处理和商品销量累加过程中,需要查询订单的商品列表:
|
||||
```java
|
||||
List<ShopOrderGoods> orderGoodsList = shopOrderGoodsService.getListByOrderId(order.getOrderId());
|
||||
```
|
||||
|
||||
但是由于租户隔离机制,可能无法查询到其他租户的订单商品信息,导致销量累加失败。
|
||||
|
||||
## 🎯 解决方案
|
||||
|
||||
实现了一个忽略租户隔离的订单商品查询方法`getListByOrderIdIgnoreTenant`,确保能够跨租户查询订单商品信息。
|
||||
|
||||
## 🔧 实现内容
|
||||
|
||||
### 1. ShopOrderGoodsService接口扩展
|
||||
|
||||
**文件**: `src/main/java/com/gxwebsoft/shop/service/ShopOrderGoodsService.java`
|
||||
|
||||
```java
|
||||
/**
|
||||
* 根据订单ID查询订单商品列表(忽略租户隔离)
|
||||
* @param orderId 订单ID
|
||||
* @return List<ShopOrderGoods>
|
||||
*/
|
||||
List<ShopOrderGoods> getListByOrderIdIgnoreTenant(Integer orderId);
|
||||
```
|
||||
|
||||
### 2. ShopOrderGoodsMapper数据库操作
|
||||
|
||||
**文件**: `src/main/java/com/gxwebsoft/shop/mapper/ShopOrderGoodsMapper.java`
|
||||
|
||||
```java
|
||||
/**
|
||||
* 根据订单ID查询订单商品列表(忽略租户隔离)
|
||||
* @param orderId 订单ID
|
||||
* @return List<ShopOrderGoods>
|
||||
*/
|
||||
@InterceptorIgnore(tenantLine = "true")
|
||||
@Select("SELECT * FROM shop_order_goods WHERE order_id = #{orderId} AND deleted = 0")
|
||||
List<ShopOrderGoods> selectListByOrderIdIgnoreTenant(@Param("orderId") Integer orderId);
|
||||
```
|
||||
|
||||
**关键特性**:
|
||||
- ✅ `@InterceptorIgnore(tenantLine = "true")` - 忽略租户隔离
|
||||
- ✅ `@Select`注解直接执行SQL查询
|
||||
- ✅ 只过滤已删除的记录,不过滤租户
|
||||
|
||||
### 3. ShopOrderGoodsServiceImpl业务实现
|
||||
|
||||
**文件**: `src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderGoodsServiceImpl.java`
|
||||
|
||||
```java
|
||||
@Override
|
||||
public List<ShopOrderGoods> getListByOrderIdIgnoreTenant(Integer orderId) {
|
||||
try {
|
||||
if (orderId == null) {
|
||||
log.warn("查询订单商品列表参数无效 - 订单ID: {}", orderId);
|
||||
return List.of();
|
||||
}
|
||||
|
||||
List<ShopOrderGoods> orderGoodsList = baseMapper.selectListByOrderIdIgnoreTenant(orderId);
|
||||
|
||||
log.info("忽略租户隔离查询订单商品成功 - 订单ID: {}, 商品数量: {}",
|
||||
orderId, orderGoodsList != null ? orderGoodsList.size() : 0);
|
||||
|
||||
return orderGoodsList != null ? orderGoodsList : List.of();
|
||||
} catch (Exception e) {
|
||||
log.error("忽略租户隔离查询订单商品异常 - 订单ID: {}", orderId, e);
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**功能特性**:
|
||||
- ✅ 参数验证 - 检查orderId的有效性
|
||||
- ✅ 异常处理 - 捕获并记录异常信息
|
||||
- ✅ 详细日志 - 记录查询结果和关键信息
|
||||
- ✅ 安全返回 - 异常时返回空列表而不是null
|
||||
|
||||
### 4. ShopOrderServiceImpl集成
|
||||
|
||||
**文件**: `src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java`
|
||||
|
||||
```java
|
||||
// 修改前(受租户隔离影响)
|
||||
final List<ShopOrderGoods> orderGoodsList = shopOrderGoodsService.getListByOrderId(order.getOrderId());
|
||||
|
||||
// 修改后(忽略租户隔离)
|
||||
final List<ShopOrderGoods> orderGoodsList = shopOrderGoodsService.getListByOrderIdIgnoreTenant(order.getOrderId());
|
||||
```
|
||||
|
||||
## 🔄 调用流程
|
||||
|
||||
```
|
||||
支付成功回调
|
||||
↓
|
||||
ShopOrderServiceImpl.updateByOutTradeNo()
|
||||
↓
|
||||
handlePaymentSuccess()
|
||||
↓
|
||||
updateGoodsSales()
|
||||
↓
|
||||
shopOrderGoodsService.getListByOrderIdIgnoreTenant() [忽略租户隔离]
|
||||
↓
|
||||
获取订单商品列表
|
||||
↓
|
||||
updateSingleGoodsSales() [累加每个商品销量]
|
||||
```
|
||||
|
||||
## 🎯 核心优势
|
||||
|
||||
### 1. 租户隔离绕过
|
||||
- ✅ 使用`@InterceptorIgnore(tenantLine = "true")`忽略租户隔离
|
||||
- ✅ 可以查询任意租户的订单商品信息
|
||||
- ✅ 确保跨租户业务逻辑正常执行
|
||||
|
||||
### 2. 数据完整性
|
||||
- ✅ 查询完整的订单商品信息
|
||||
- ✅ 包含商品ID、名称、数量等关键信息
|
||||
- ✅ 与普通查询返回相同的数据结构
|
||||
|
||||
### 3. 错误处理
|
||||
- ✅ 完善的参数验证
|
||||
- ✅ 异常捕获和日志记录
|
||||
- ✅ 安全的返回值处理
|
||||
|
||||
### 4. 性能优化
|
||||
- ✅ 直接SQL查询,避免复杂的条件构建
|
||||
- ✅ 单次查询获取所有订单商品
|
||||
- ✅ 减少数据库交互次数
|
||||
|
||||
## 🧪 测试验证
|
||||
|
||||
**测试文件**: `src/test/java/com/gxwebsoft/shop/service/ShopOrderGoodsIgnoreTenantTest.java`
|
||||
|
||||
### 测试用例
|
||||
1. **基本功能测试** - 验证忽略租户隔离查询订单商品
|
||||
2. **参数验证测试** - 验证null值和无效ID的处理
|
||||
3. **跨租户查询测试** - 验证查询不同租户订单商品的能力
|
||||
4. **批量查询性能测试** - 验证批量查询的性能表现
|
||||
|
||||
### 运行测试
|
||||
```bash
|
||||
# 运行单个测试类
|
||||
mvn test -Dtest=ShopOrderGoodsIgnoreTenantTest
|
||||
|
||||
# 运行特定测试方法
|
||||
mvn test -Dtest=ShopOrderGoodsIgnoreTenantTest#testGetListByOrderIdIgnoreTenant
|
||||
```
|
||||
|
||||
## 📋 对比分析
|
||||
|
||||
| 方法 | 租户隔离 | 使用场景 | 安全性 |
|
||||
|-----|---------|----------|--------|
|
||||
| `getListByOrderId()` | ✅ 受限制 | 普通业务查询 | 高 |
|
||||
| `getListByOrderIdIgnoreTenant()` | ❌ 忽略 | 跨租户业务处理 | 中等 |
|
||||
|
||||
## 🔍 使用场景
|
||||
|
||||
### 1. 支付回调处理
|
||||
```java
|
||||
// 在支付回调中需要查询订单商品进行销量累加
|
||||
List<ShopOrderGoods> orderGoodsList = shopOrderGoodsService.getListByOrderIdIgnoreTenant(order.getOrderId());
|
||||
for (ShopOrderGoods orderGoods : orderGoodsList) {
|
||||
// 累加商品销量
|
||||
shopGoodsService.addSaleCount(orderGoods.getGoodsId(), orderGoods.getTotalNum());
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 跨租户订单处理
|
||||
```java
|
||||
// 需要处理其他租户订单的商品信息
|
||||
List<ShopOrderGoods> crossTenantOrderGoods = shopOrderGoodsService.getListByOrderIdIgnoreTenant(otherTenantOrderId);
|
||||
if (!crossTenantOrderGoods.isEmpty()) {
|
||||
// 执行跨租户业务逻辑
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 监控和日志
|
||||
|
||||
### 成功日志
|
||||
```
|
||||
忽略租户隔离查询订单商品成功 - 订单ID: 123, 商品数量: 3
|
||||
```
|
||||
|
||||
### 失败日志
|
||||
```
|
||||
查询订单商品列表参数无效 - 订单ID: null
|
||||
忽略租户隔离查询订单商品异常 - 订单ID: 123
|
||||
```
|
||||
|
||||
### 业务日志
|
||||
```java
|
||||
log.info("订单商品详情 - ID: {}, 商品ID: {}, 商品名称: {}, 数量: {}",
|
||||
orderGoods.getId(), orderGoods.getGoodsId(),
|
||||
orderGoods.getGoodsName(), orderGoods.getTotalNum());
|
||||
```
|
||||
|
||||
## 🔒 安全考虑
|
||||
|
||||
### 1. 使用场景限制
|
||||
- 仅在确实需要跨租户查询时使用
|
||||
- 主要用于内部业务逻辑,不暴露给前端
|
||||
- 避免在普通的CRUD操作中使用
|
||||
|
||||
### 2. 数据安全
|
||||
- 确保调用方有合理的业务需求
|
||||
- 记录关键操作日志
|
||||
- 避免敏感信息泄露
|
||||
|
||||
### 3. 性能考虑
|
||||
- 在高并发场景下谨慎使用
|
||||
- 考虑添加缓存机制
|
||||
- 监控查询性能
|
||||
|
||||
## ✅ 验证清单
|
||||
|
||||
- [x] ShopOrderGoodsService接口添加getListByOrderIdIgnoreTenant方法
|
||||
- [x] ShopOrderGoodsMapper添加selectListByOrderIdIgnoreTenant方法
|
||||
- [x] 使用@InterceptorIgnore忽略租户隔离
|
||||
- [x] ShopOrderGoodsServiceImpl实现业务逻辑
|
||||
- [x] ShopOrderServiceImpl使用新方法
|
||||
- [x] 添加完善的参数验证和异常处理
|
||||
- [x] 创建测试用例验证功能
|
||||
- [x] 添加详细的日志记录
|
||||
|
||||
## 🎉 总结
|
||||
|
||||
订单商品忽略租户隔离查询功能已完整实现,具备以下特性:
|
||||
- **跨租户能力**: 忽略租户隔离,可查询任意租户的订单商品
|
||||
- **数据完整性**: 返回完整的订单商品信息
|
||||
- **安全可控**: 仅在特定业务场景使用,不暴露给前端
|
||||
- **性能优化**: 直接SQL查询,高效获取数据
|
||||
- **错误处理**: 完善的异常处理和日志记录
|
||||
|
||||
现在在支付回调等跨租户业务场景中,可以正确查询到订单商品信息,确保商品销量累加功能正常工作,不会因为租户隔离导致查询失败。
|
||||
Reference in New Issue
Block a user