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.
3.1 KiB
3.1 KiB
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 脚本(手动执行,部署时跑):
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 是确定性的,没有数据丢失风险。