小程序开发-服务端
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.5 KiB

订单商品忽略租户隔离查询功能实现

🔍 问题背景

在支付回调处理和商品销量累加过程中,需要查询订单的商品列表:

List<ShopOrderGoods> orderGoodsList = shopOrderGoodsService.getListByOrderId(order.getOrderId());

但是由于租户隔离机制,可能无法查询到其他租户的订单商品信息,导致销量累加失败。

🎯 解决方案

实现了一个忽略租户隔离的订单商品查询方法getListByOrderIdIgnoreTenant,确保能够跨租户查询订单商品信息。

🔧 实现内容

1. ShopOrderGoodsService接口扩展

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

/**
 * 根据订单ID查询订单商品列表(忽略租户隔离)
 * @param orderId 订单ID
 * @return List<ShopOrderGoods>
 */
List<ShopOrderGoods> getListByOrderIdIgnoreTenant(Integer orderId);

2. ShopOrderGoodsMapper数据库操作

文件: src/main/java/com/gxwebsoft/shop/mapper/ShopOrderGoodsMapper.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

@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

// 修改前(受租户隔离影响)
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. 批量查询性能测试 - 验证批量查询的性能表现

运行测试

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

# 运行特定测试方法
mvn test -Dtest=ShopOrderGoodsIgnoreTenantTest#testGetListByOrderIdIgnoreTenant

📋 对比分析

方法 租户隔离 使用场景 安全性
getListByOrderId() 受限制 普通业务查询
getListByOrderIdIgnoreTenant() 忽略 跨租户业务处理 中等

🔍 使用场景

1. 支付回调处理

// 在支付回调中需要查询订单商品进行销量累加
List<ShopOrderGoods> orderGoodsList = shopOrderGoodsService.getListByOrderIdIgnoreTenant(order.getOrderId());
for (ShopOrderGoods orderGoods : orderGoodsList) {
    // 累加商品销量
    shopGoodsService.addSaleCount(orderGoods.getGoodsId(), orderGoods.getTotalNum());
}

2. 跨租户订单处理

// 需要处理其他租户订单的商品信息
List<ShopOrderGoods> crossTenantOrderGoods = shopOrderGoodsService.getListByOrderIdIgnoreTenant(otherTenantOrderId);
if (!crossTenantOrderGoods.isEmpty()) {
    // 执行跨租户业务逻辑
}

📊 监控和日志

成功日志

忽略租户隔离查询订单商品成功 - 订单ID: 123, 商品数量: 3

失败日志

查询订单商品列表参数无效 - 订单ID: null
忽略租户隔离查询订单商品异常 - 订单ID: 123

业务日志

log.info("订单商品详情 - ID: {}, 商品ID: {}, 商品名称: {}, 数量: {}", 
    orderGoods.getId(), orderGoods.getGoodsId(), 
    orderGoods.getGoodsName(), orderGoods.getTotalNum());

🔒 安全考虑

1. 使用场景限制

  • 仅在确实需要跨租户查询时使用
  • 主要用于内部业务逻辑,不暴露给前端
  • 避免在普通的CRUD操作中使用

2. 数据安全

  • 确保调用方有合理的业务需求
  • 记录关键操作日志
  • 避免敏感信息泄露

3. 性能考虑

  • 在高并发场景下谨慎使用
  • 考虑添加缓存机制
  • 监控查询性能

验证清单

  • ShopOrderGoodsService接口添加getListByOrderIdIgnoreTenant方法
  • ShopOrderGoodsMapper添加selectListByOrderIdIgnoreTenant方法
  • 使用@InterceptorIgnore忽略租户隔离
  • ShopOrderGoodsServiceImpl实现业务逻辑
  • ShopOrderServiceImpl使用新方法
  • 添加完善的参数验证和异常处理
  • 创建测试用例验证功能
  • 添加详细的日志记录

🎉 总结

订单商品忽略租户隔离查询功能已完整实现,具备以下特性:

  • 跨租户能力: 忽略租户隔离,可查询任意租户的订单商品
  • 数据完整性: 返回完整的订单商品信息
  • 安全可控: 仅在特定业务场景使用,不暴露给前端
  • 性能优化: 直接SQL查询,高效获取数据
  • 错误处理: 完善的异常处理和日志记录

现在在支付回调等跨租户业务场景中,可以正确查询到订单商品信息,确保商品销量累加功能正常工作,不会因为租户隔离导致查询失败。