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.
93 lines
3.1 KiB
93 lines
3.1 KiB
|
4 weeks ago
|
# 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 是确定性的,没有数据丢失风险。
|