Files
youlai-boot/docs/多租户用户管理改进说明.md
2025-12-11 08:18:01 +08:00

229 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 多租户用户管理改进说明
## 改进概述
本次改进实现了在用户管理中自动维护 `sys_user_tenant` 关联表,支持单租户和多租户两种模式的无缝切换。
## 核心改进
### 1. 用户新增时自动创建租户关联
**修改文件**: `UserServiceImpl.saveUser()`
**逻辑**:
- 创建用户后,判断是否启用多租户(通过 `youlai.tenant.enabled` 配置)
- 如果启用,自动向 `sys_user_tenant` 表插入关联记录
- 新用户默认设置为该租户的默认租户(`is_default=1`
```java
// 新增用户
boolean result = this.save(entity);
if (result) {
// 保存用户角色
userRoleService.saveUserRoles(entity.getId(), userForm.getRoleIds());
// 如果启用多租户,保存用户租户关联
if (Boolean.TRUE.equals(tenantProperties.getEnabled())) {
saveUserTenantRelation(entity.getId(), entity.getTenantId(), true);
}
}
```
### 2. 用户更新时同步租户关联
**修改文件**: `UserServiceImpl.updateUser()`
**逻辑**:
- 比较用户的旧租户ID和新租户ID
- 如果租户发生变更:
- 删除旧的租户关联记录
- 创建新的租户关联记录
```java
// 如果启用多租户且租户发生变更,更新用户租户关联
if (Boolean.TRUE.equals(tenantProperties.getEnabled())) {
Long newTenantId = entity.getTenantId();
if (newTenantId != null && !newTenantId.equals(oldTenantId)) {
// 删除旧的租户关联
if (oldTenantId != null) {
userTenantMapper.delete(...);
}
// 保存新的租户关联
saveUserTenantRelation(userId, newTenantId, true);
}
}
```
### 3. 用户删除时清理租户关联
**修改文件**: `UserServiceImpl.deleteUsers()`
**逻辑**:
- 删除用户后,自动清理 `sys_user_tenant` 表中的关联记录
- 避免产生孤立数据
```java
boolean result = this.removeByIds(ids);
// 如果启用多租户,删除用户租户关联
if (result && Boolean.TRUE.equals(tenantProperties.getEnabled())) {
for (Long userId : ids) {
userTenantMapper.delete(...);
log.info("删除用户租户关联userId={}", userId);
}
}
```
### 4. 新增私有方法处理关联逻辑
**新增方法**: `saveUserTenantRelation()`
**功能**:
- 检查关联是否已存在
- 存在则更新 `is_default` 标识
- 不存在则插入新记录
- 添加详细日志记录
## 配置说明
### 启用多租户
`application-dev.yml` 中配置:
```yaml
youlai:
tenant:
enabled: true # 设置为 true 启用多租户
column: tenant_id
default-tenant-id: 1
```
### 禁用多租户
```yaml
youlai:
tenant:
enabled: false # 设置为 false 禁用多租户
```
当禁用多租户时:
- ✅ 不会自动创建/更新/删除 `sys_user_tenant` 记录
- ✅ 只使用 `sys_user.tenant_id` 字段
- ✅ 零成本切换,无需修改代码
## 数据库设计
### sys_user 表
```sql
ALTER TABLE `sys_user`
ADD COLUMN `tenant_id` bigint DEFAULT 1 COMMENT '租户ID' AFTER `id`,
ADD INDEX `idx_tenant_id` (`tenant_id`);
```
### sys_user_tenant 表
```sql
CREATE TABLE `sys_user_tenant` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`user_id` bigint NOT NULL COMMENT '用户ID',
`tenant_id` bigint NOT NULL COMMENT '租户ID',
`is_default` tinyint DEFAULT '0' COMMENT '是否默认租户(1-是 0-否)',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_tenant` (`user_id`, `tenant_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户租户关联表(多租户模式)';
```
## 数据初始化
执行 SQL 脚本时,会自动为现有用户创建租户关联:
```sql
INSERT INTO `sys_user_tenant` (`user_id`, `tenant_id`, `is_default`)
SELECT `id`, 1, 1 FROM `sys_user` WHERE `is_deleted` = 0
ON DUPLICATE KEY UPDATE `is_default` = 1;
```
## 使用场景
### 场景1单租户模式
- 配置:`youlai.tenant.enabled = false`
- 用户只属于一个租户
- 数据完全隔离
- 不需要租户切换功能
### 场景2多租户模式
- 配置:`youlai.tenant.enabled = true`
- 用户可以属于多个租户
- 可以在不同租户间切换
- 通过 `sys_user_tenant` 表管理关联关系
## 关键优势
1. **自动化管理**: 创建/更新/删除用户时自动维护关联表
2. **灵活切换**: 通过配置即可在单租户和多租户模式间切换
3. **数据一致性**: 确保 `sys_user.tenant_id``sys_user_tenant` 表数据同步
4. **幂等操作**: 支持重复执行,避免重复插入
5. **完整日志**: 每次操作都有日志记录,便于追踪问题
## 注意事项
1. **事务处理**: 用户的增删改操作都已添加事务注解 `@Transactional`
2. **空值检查**: `saveUserTenantRelation()` 方法会检查参数是否为空
3. **幂等性**: 插入前会检查记录是否已存在
4. **配置优先**: 所有操作都基于 `tenantProperties.getEnabled()` 判断
## 测试建议
### 测试场景1多租户模式下创建用户
1. 设置 `youlai.tenant.enabled = true`
2. 在租户A下创建用户"张三"
3. 验证:
- `sys_user` 表插入记录,`tenant_id=A`
- `sys_user_tenant` 表插入记录,`user_id=张三, tenant_id=A, is_default=1`
### 测试场景2多租户模式下更新用户租户
1. 将用户"张三"从租户A转移到租户B
2. 验证:
- `sys_user` 表更新,`tenant_id=B`
- `sys_user_tenant` 表删除旧记录 (A),插入新记录 (B)
### 测试场景3多租户模式下删除用户
1. 删除用户"张三"
2. 验证:
- `sys_user` 表标记为删除
- `sys_user_tenant` 表删除关联记录
### 测试场景4单租户模式
1. 设置 `youlai.tenant.enabled = false`
2. 创建/更新/删除用户
3. 验证:
- 只操作 `sys_user`
- 不操作 `sys_user_tenant`
## 修改文件清单
-`UserServiceImpl.java` - 添加多租户关联维护逻辑
-`tenant_add.sql` - 数据库表结构和初始化脚本
-`TenantProperties.java` - 多租户配置类(已存在)
-`UserTenantMapper.java` - MyBatis Mapper已存在
-`UserTenant.java` - 实体类(已存在)
## 向后兼容性
- ✅ 默认配置为 `enabled: false`,不影响现有单租户系统
- ✅ 现有代码无需修改,只需调整配置文件即可启用多租户
- ✅ 数据库升级脚本支持多次执行(幂等)
## 总结
本次改进完善了多租户用户管理机制,实现了:
- 自动维护用户租户关联关系
- 支持单/多租户模式灵活切换
- 保证数据一致性和完整性
- 提供详细的操作日志
系统现在可以零成本在单租户和多租户模式间切换,只需修改配置文件即可。