# 多租户用户管理改进说明 ## 改进概述 本次改进实现了在用户管理中自动维护 `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`,不影响现有单租户系统 - ✅ 现有代码无需修改,只需调整配置文件即可启用多租户 - ✅ 数据库升级脚本支持多次执行(幂等) ## 总结 本次改进完善了多租户用户管理机制,实现了: - 自动维护用户租户关联关系 - 支持单/多租户模式灵活切换 - 保证数据一致性和完整性 - 提供详细的操作日志 系统现在可以零成本在单租户和多租户模式间切换,只需修改配置文件即可。