# 03 · 迁移策略:现有角色单一档位 → 多模块档位 Type: grilling Status: resolved Blocked by: 02 ## Question 现有角色的单一 `sys_role.data_scope` 值,如何迁移到新的角色×模块档位存储? 要定的点: - 迁移规则:把老的单一档位复制到**每个已知模块**(四个都用这一档),还是别的映射? - 迁移时点/形式:Flyway/Liquibase 脚本?`DataInitializer` 里补?一次性 SQL? (查现状:本 repo 用什么做 schema 迁移。) - 内置角色(ADMIN,builtin=true,现 data_scope=ALL)迁移后各模块是否仍 ALL。 - 迁移可逆性 / 回滚考量。 依赖 02 定下的新存储结构。 ## Answer ### 1. 迁移规则 旧 `sys_role.data_scope` 单值复制到每个已知模块(lead / opportunity / customer / project),值相同。 - ADMIN(builtin=true,ALL)→ 每模块各一行 ALL。 - 其他角色同理:旧值是 DEPT 就四个模块都是 DEPT。 - 旧值为 null 的角色不产生行(走默认 SELF,02 决策 3)。 ### 2. 迁移机制:一次性 SQL 脚本(单事务) 本 repo 无 Flyway/Liquibase,无 SQL 迁移脚本目录。用一次性 SQL 脚本(手动执行,部署时跑): ```sql BEGIN; -- 1. 建模块注册表 CREATE TABLE sys_data_scope_module ( id bigint PK AUTO_INCREMENT, code varchar(50) NOT NULL UNIQUE, name varchar(100) NOT NULL, sort int NOT NULL DEFAULT 0, status varchar(10) NOT NULL DEFAULT 'enabled', builtin boolean NOT NULL DEFAULT false ); -- 2. 插入内置模块 INSERT INTO sys_data_scope_module (code, name, sort, builtin) VALUES ('lead', '线索', 1, true), ('opportunity', '商机', 2, true), ('customer', '客户', 3, true), ('project', '项目', 4, true); -- 3. 建角色×模块档位表 CREATE TABLE sys_role_data_scope ( id bigint PK AUTO_INCREMENT, role_id bigint NOT NULL, module_code varchar(50) NOT NULL, data_scope tinyint NOT NULL, UNIQUE KEY uk_role_module (role_id, module_code) ); -- 4. 迁移:旧单值复制到每模块 INSERT INTO sys_role_data_scope (role_id, module_code, data_scope) SELECT r.id, m.code, r.data_scope FROM sys_role r CROSS JOIN sys_data_scope_module m WHERE r.data_scope IS NOT NULL; -- 5. 删旧列 ALTER TABLE sys_role DROP COLUMN data_scope; COMMIT; ``` - 单事务保证原子性:要么全成功,要么全回滚。 - `CROSS JOIN` 把旧值复制到每个模块。 - 步骤 5 删旧列在同一个事务里——一步到位(用户决策)。 ### 3. DataInitializer 同步改 - `adminRole.setDataScope(DataScopeEnum.ALL.getValue())` 删除。 - ADMIN 角色创建后,往 `sys_role_data_scope` 为每个模块插 ALL 行(幂等检查:先查行是否存在)。 - 新增内置模块初始化:往 `sys_data_scope_module` 插入四个内置模块(幂等检查)。 - `SysRole.dataScope` 字段删除。 ### 4. 回滚考量 - SQL 脚本是单事务,失败自动回滚。 - 成功后旧列已删,无法从 SQL 层面回滚。如需回滚:从备份恢复旧列,删新表数据,重跑 DataInitializer。 - 实际风险低:CROSS JOIN 是确定性的,没有数据丢失风险。