feat(shop): 实现商品销量累加和跨租户查询功能
- 添加商品销量累加功能,确保支付成功后更新销量- 实现跨租户查询用户和订单商品的功能 - 修复支付回调中的错误代码 -优化日志记录和异常处理
This commit is contained in:
228
docs/用户忽略租户隔离查询功能.md
Normal file
228
docs/用户忽略租户隔离查询功能.md
Normal file
@@ -0,0 +1,228 @@
|
||||
# 用户忽略租户隔离查询功能实现
|
||||
|
||||
## 🔍 问题背景
|
||||
|
||||
在`ShopOrderUpdate10550ServiceImpl.java`中,需要根据订单的用户ID查询用户信息:
|
||||
```java
|
||||
final User user = userService.getById(order.getUserId());
|
||||
```
|
||||
|
||||
但是由于租户隔离机制,可能无法查询到其他租户的用户信息,导致业务逻辑失败。
|
||||
|
||||
## 🎯 解决方案
|
||||
|
||||
实现了一个忽略租户隔离的用户查询方法`getByIdIgnoreTenant`,确保能够跨租户查询用户信息。
|
||||
|
||||
## 🔧 实现内容
|
||||
|
||||
### 1. UserService接口扩展
|
||||
|
||||
**文件**: `src/main/java/com/gxwebsoft/common/system/service/UserService.java`
|
||||
|
||||
```java
|
||||
/**
|
||||
* 根据用户ID查询用户(忽略租户隔离)
|
||||
* @param userId 用户ID
|
||||
* @return User
|
||||
*/
|
||||
User getByIdIgnoreTenant(Integer userId);
|
||||
```
|
||||
|
||||
### 2. UserMapper数据库操作
|
||||
|
||||
**文件**: `src/main/java/com/gxwebsoft/common/system/mapper/UserMapper.java`
|
||||
|
||||
```java
|
||||
/**
|
||||
* 根据用户ID查询用户(忽略租户隔离)
|
||||
* @param userId 用户ID
|
||||
* @return User
|
||||
*/
|
||||
@InterceptorIgnore(tenantLine = "true")
|
||||
User selectByIdIgnoreTenant(@Param("userId") Integer userId);
|
||||
```
|
||||
|
||||
**关键特性**:
|
||||
- ✅ `@InterceptorIgnore(tenantLine = "true")` - 忽略租户隔离
|
||||
- ✅ 支持跨租户查询用户信息
|
||||
|
||||
### 3. UserServiceImpl业务实现
|
||||
|
||||
**文件**: `src/main/java/com/gxwebsoft/common/system/service/impl/UserServiceImpl.java`
|
||||
|
||||
```java
|
||||
@Override
|
||||
public User getByIdIgnoreTenant(Integer userId) {
|
||||
if (userId == null) {
|
||||
return null;
|
||||
}
|
||||
return baseMapper.selectByIdIgnoreTenant(userId);
|
||||
}
|
||||
```
|
||||
|
||||
**功能特性**:
|
||||
- ✅ 参数验证 - 检查userId的有效性
|
||||
- ✅ 空值处理 - userId为null时返回null
|
||||
- ✅ 忽略租户隔离 - 可以查询任意租户的用户
|
||||
|
||||
### 4. UserMapper.xml SQL映射
|
||||
|
||||
**文件**: `src/main/java/com/gxwebsoft/common/system/mapper/xml/UserMapper.xml`
|
||||
|
||||
```xml
|
||||
<!-- 根据用户ID查询用户(忽略租户隔离) -->
|
||||
<select id="selectByIdIgnoreTenant" resultType="com.gxwebsoft.common.system.entity.User">
|
||||
SELECT a.*,
|
||||
c.dict_data_name sex_name,
|
||||
e.tenant_name,
|
||||
h.dealer_id
|
||||
FROM gxwebsoft_core.sys_user a
|
||||
LEFT JOIN (
|
||||
<include refid="selectSexDictSql"/>
|
||||
) c ON a.sex = c.dict_data_code
|
||||
LEFT JOIN gxwebsoft_core.sys_tenant e ON a.tenant_id = e.tenant_id
|
||||
LEFT JOIN gxwebsoft_core.sys_user_referee h ON a.user_id = h.user_id and h.deleted = 0
|
||||
WHERE a.user_id = #{userId}
|
||||
AND a.deleted = 0
|
||||
</select>
|
||||
```
|
||||
|
||||
**SQL特性**:
|
||||
- ✅ 完整的用户信息查询(包括关联表)
|
||||
- ✅ 包含性别字典、租户信息、推荐人信息
|
||||
- ✅ 只过滤已删除的用户,不过滤租户
|
||||
|
||||
### 5. ShopOrderUpdate10550ServiceImpl集成
|
||||
|
||||
**文件**: `src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderUpdate10550ServiceImpl.java`
|
||||
|
||||
```java
|
||||
// 修改前(受租户隔离影响)
|
||||
final User user = userService.getById(order.getUserId());
|
||||
|
||||
// 修改后(忽略租户隔离)
|
||||
final User user = userService.getByIdIgnoreTenant(order.getUserId());
|
||||
```
|
||||
|
||||
## 🔄 使用场景
|
||||
|
||||
### 1. 支付回调处理
|
||||
```java
|
||||
// 在支付回调中需要查询订单用户信息
|
||||
final User user = userService.getByIdIgnoreTenant(order.getUserId());
|
||||
if (user != null) {
|
||||
// 处理用户相关业务逻辑
|
||||
log.info("用户信息 - ID: {}, 用户名: {}, 租户: {}",
|
||||
user.getUserId(), user.getUsername(), user.getTenantId());
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 跨租户业务处理
|
||||
```java
|
||||
// 需要处理其他租户用户的业务
|
||||
User crossTenantUser = userService.getByIdIgnoreTenant(otherTenantUserId);
|
||||
if (crossTenantUser != null) {
|
||||
// 执行跨租户业务逻辑
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 核心优势
|
||||
|
||||
### 1. 租户隔离绕过
|
||||
- ✅ 使用`@InterceptorIgnore(tenantLine = "true")`忽略租户隔离
|
||||
- ✅ 可以查询任意租户的用户信息
|
||||
- ✅ 不受当前登录用户租户限制
|
||||
|
||||
### 2. 数据完整性
|
||||
- ✅ 查询完整的用户信息(包括关联数据)
|
||||
- ✅ 包含性别字典、租户信息、推荐人信息
|
||||
- ✅ 与普通查询返回相同的数据结构
|
||||
|
||||
### 3. 安全性考虑
|
||||
- ✅ 仅在特定业务场景使用
|
||||
- ✅ 不暴露给前端接口
|
||||
- ✅ 主要用于内部业务逻辑处理
|
||||
|
||||
### 4. 性能优化
|
||||
- ✅ 单次查询获取完整信息
|
||||
- ✅ 复用现有的SQL结构
|
||||
- ✅ 避免多次查询关联数据
|
||||
|
||||
## 🧪 测试验证
|
||||
|
||||
**测试文件**: `src/test/java/com/gxwebsoft/common/system/service/UserIgnoreTenantTest.java`
|
||||
|
||||
### 测试用例
|
||||
1. **基本功能测试** - 验证忽略租户隔离查询
|
||||
2. **参数验证测试** - 验证null值和无效ID的处理
|
||||
3. **跨租户查询测试** - 验证查询不同租户用户的能力
|
||||
|
||||
### 运行测试
|
||||
```bash
|
||||
# 运行单个测试类
|
||||
mvn test -Dtest=UserIgnoreTenantTest
|
||||
|
||||
# 运行特定测试方法
|
||||
mvn test -Dtest=UserIgnoreTenantTest#testGetByIdIgnoreTenant
|
||||
```
|
||||
|
||||
## 📋 对比分析
|
||||
|
||||
| 方法 | 租户隔离 | 使用场景 | 安全性 |
|
||||
|-----|---------|----------|--------|
|
||||
| `getById()` | ✅ 受限制 | 普通业务查询 | 高 |
|
||||
| `getByIdIgnoreTenant()` | ❌ 忽略 | 跨租户业务处理 | 中等 |
|
||||
|
||||
## 🔍 使用注意事项
|
||||
|
||||
### 1. 使用场景限制
|
||||
- 仅在确实需要跨租户查询时使用
|
||||
- 主要用于内部业务逻辑,不暴露给前端
|
||||
- 避免在普通的CRUD操作中使用
|
||||
|
||||
### 2. 安全考虑
|
||||
- 确保调用方有合理的业务需求
|
||||
- 记录关键操作日志
|
||||
- 避免敏感信息泄露
|
||||
|
||||
### 3. 性能考虑
|
||||
- 查询结果包含关联数据,注意性能影响
|
||||
- 在高并发场景下谨慎使用
|
||||
- 考虑添加缓存机制
|
||||
|
||||
## 📊 监控和日志
|
||||
|
||||
### 使用日志
|
||||
```java
|
||||
log.info("跨租户查询用户 - 用户ID: {}, 查询结果: {}",
|
||||
userId, user != null ? "成功" : "失败");
|
||||
```
|
||||
|
||||
### 业务日志
|
||||
```java
|
||||
if (user != null) {
|
||||
log.info("用户信息 - ID: {}, 用户名: {}, 租户ID: {}",
|
||||
user.getUserId(), user.getUsername(), user.getTenantId());
|
||||
}
|
||||
```
|
||||
|
||||
## ✅ 验证清单
|
||||
|
||||
- [x] UserService接口添加getByIdIgnoreTenant方法
|
||||
- [x] UserMapper添加selectByIdIgnoreTenant方法
|
||||
- [x] 使用@InterceptorIgnore忽略租户隔离
|
||||
- [x] UserServiceImpl实现业务逻辑
|
||||
- [x] UserMapper.xml添加SQL映射
|
||||
- [x] ShopOrderUpdate10550ServiceImpl使用新方法
|
||||
- [x] 添加参数验证和空值处理
|
||||
- [x] 创建测试用例验证功能
|
||||
|
||||
## 🎉 总结
|
||||
|
||||
用户忽略租户隔离查询功能已完整实现,具备以下特性:
|
||||
- **跨租户能力**: 忽略租户隔离,可查询任意租户用户
|
||||
- **数据完整性**: 返回完整的用户信息和关联数据
|
||||
- **安全可控**: 仅在特定业务场景使用,不暴露给前端
|
||||
- **性能优化**: 单次查询获取完整信息
|
||||
|
||||
现在在支付回调等跨租户业务场景中,可以正确查询到用户信息,不会因为租户隔离导致查询失败。
|
||||
Reference in New Issue
Block a user