diff --git a/RuoYi-Vue/sql/generator/kingbase/001_generator_identity_precheck.sql b/RuoYi-Vue/sql/generator/kingbase/001_generator_identity_precheck.sql
new file mode 100644
index 000000000..cb61e7720
--- /dev/null
+++ b/RuoYi-Vue/sql/generator/kingbase/001_generator_identity_precheck.sql
@@ -0,0 +1,91 @@
+-- ==============================================================================
+-- 001_generator_identity_precheck.sql
+-- Generator Kingbase Identity 预检只读脚本 (增强版: 支持 Partial 状态与数据量探测)
+--
+-- 功能:只读探测 gen_table.table_id 与 gen_table_column.column_id 的 Identity 状态
+-- 判定准则:
+-- 1. CASE_1_BOTH_NEED_PATCH: 两列均缺失 Identity,需依次执行 002a 和 002b
+-- 2. CASE_2_BOTH_ALREADY_PATCHED: 两列均已具备 Identity,禁止重复执行任何 Patch
+-- 3. CASE_3_ONLY_COLUMN_NEEDS_PATCH: 仅 column_id 缺失,严禁执行 002a,仅执行 002b
+-- 4. CASE_4_ONLY_TABLE_NEEDS_PATCH: 仅 table_id 缺失,严禁执行 002b,仅执行 002a
+-- 安全说明:纯只读查询,无任何 DDL / DML / 序列修改副作用
+-- ==============================================================================
+
+-- 1. 列级别 Identity 详细属性检查
+SELECT
+ c.relname AS table_name,
+ a.attname AS column_name,
+ t.typname AS data_type,
+ a.attnotnull AS is_not_null,
+ COALESCE(a.attidentity, '') AS attidentity,
+ CASE a.attidentity
+ WHEN 'd' THEN 'ALREADY_PATCHED (GENERATED BY DEFAULT AS IDENTITY)'
+ WHEN 'a' THEN 'ALREADY_PATCHED (GENERATED ALWAYS AS IDENTITY)'
+ ELSE 'NEED_PATCH (MISSING_IDENTITY)'
+ END AS patch_status
+FROM sys_class c
+JOIN sys_attribute a ON a.attrelid = c.oid
+JOIN sys_type t ON a.atttypid = t.oid
+JOIN sys_namespace n ON n.oid = c.relnamespace
+WHERE n.nspname = 'public'
+ AND ((c.relname = 'gen_table' AND a.attname = 'table_id')
+ OR (c.relname = 'gen_table_column' AND a.attname = 'column_id'))
+ORDER BY c.relname, a.attname;
+
+-- 2. 检查关联 Sequence 存在性
+SELECT
+ c.relname AS sequence_name,
+ c.relkind AS relkind,
+ CASE c.relkind
+ WHEN 'S' THEN 'SEQUENCE_EXISTS'
+ ELSE 'UNKNOWN'
+ END AS seq_status
+FROM sys_class c
+JOIN sys_namespace n ON n.oid = c.relnamespace
+WHERE n.nspname = 'public'
+ AND c.relname IN ('gen_table_table_id_seq', 'gen_table_column_column_id_seq')
+ORDER BY c.relname;
+
+-- 3. 现有数据行数与最大 ID 统计 (区分空表与已有数据环境)
+SELECT
+ 'gen_table' AS table_name,
+ COUNT(*) AS row_count,
+ COALESCE(MAX(table_id), 0) AS max_id,
+ CASE WHEN COUNT(*) = 0 THEN 'EMPTY_METADATA_ENV (默认起始序列即可安全使用)'
+ ELSE 'EXISTING_METADATA_ENV (补丁后需重点核验 Sequence 对齐)' END AS env_type
+FROM gen_table
+UNION ALL
+SELECT
+ 'gen_table_column' AS table_name,
+ COUNT(*) AS row_count,
+ COALESCE(MAX(column_id), 0) AS max_id,
+ CASE WHEN COUNT(*) = 0 THEN 'EMPTY_METADATA_ENV (默认起始序列即可安全使用)'
+ ELSE 'EXISTING_METADATA_ENV (补丁后需重点核验 Sequence 对齐)' END AS env_type
+FROM gen_table_column;
+
+-- 4. 全局 Partial / Full 状态判定与执行建议
+WITH status_data AS (
+ SELECT
+ MAX(CASE WHEN c.relname = 'gen_table' AND a.attname = 'table_id' THEN COALESCE(a.attidentity, '') END) AS table_id_id,
+ MAX(CASE WHEN c.relname = 'gen_table_column' AND a.attname = 'column_id' THEN COALESCE(a.attidentity, '') END) AS column_id_id
+ FROM sys_class c
+ JOIN sys_attribute a ON a.attrelid = c.oid
+ JOIN sys_namespace n ON n.oid = c.relnamespace
+ WHERE n.nspname = 'public'
+ AND ((c.relname = 'gen_table' AND a.attname = 'table_id')
+ OR (c.relname = 'gen_table_column' AND a.attname = 'column_id'))
+)
+SELECT
+ CASE
+ WHEN table_id_id IN ('d', 'a') AND column_id_id IN ('d', 'a') THEN
+ 'CASE_2_BOTH_ALREADY_PATCHED: 两列均已配置 Identity,禁止执行任何 Patch,直接运行 003_generator_identity_verify.sql'
+ WHEN table_id_id NOT IN ('d', 'a') AND column_id_id NOT IN ('d', 'a') THEN
+ 'CASE_1_BOTH_NEED_PATCH: 两列均缺失 Identity,需依次执行 002a_gen_table_identity_patch.sql 与 002b_gen_table_column_identity_patch.sql'
+ WHEN table_id_id IN ('d', 'a') AND column_id_id NOT IN ('d', 'a') THEN
+ 'CASE_3_ONLY_COLUMN_NEEDS_PATCH: 仅 column_id 缺失,严禁执行 002a,仅可执行 002b_gen_table_column_identity_patch.sql'
+ WHEN table_id_id NOT IN ('d', 'a') AND column_id_id IN ('d', 'a') THEN
+ 'CASE_4_ONLY_TABLE_NEEDS_PATCH: 仅 table_id 缺失,严禁执行 002b,仅可执行 002a_gen_table_identity_patch.sql'
+ ELSE
+ 'CASE_UNKNOWN: 异常状态,请联系管理员核实'
+ END AS precheck_scenario_verdict
+FROM status_data;
diff --git a/RuoYi-Vue/sql/generator/kingbase/002a_gen_table_identity_patch.sql b/RuoYi-Vue/sql/generator/kingbase/002a_gen_table_identity_patch.sql
new file mode 100644
index 000000000..36ca07a53
--- /dev/null
+++ b/RuoYi-Vue/sql/generator/kingbase/002a_gen_table_identity_patch.sql
@@ -0,0 +1,22 @@
+-- ==============================================================================
+-- 002a_gen_table_identity_patch.sql
+-- Generator Kingbase Identity 独立补丁 A: gen_table.table_id
+--
+-- 变更目标:
+-- 为 public.gen_table.table_id 添加 GENERATED BY DEFAULT AS IDENTITY
+--
+-- 执行准入前置条件(强制要求):
+-- 1. 必须先执行 001_generator_identity_precheck.sql;
+-- 2. 仅当 Precheck 判定结果为 CASE_1_BOTH_NEED_PATCH 或 CASE_4_ONLY_TABLE_NEEDS_PATCH 时方可执行;
+-- 3. 若 table_id 已为 ALREADY_PATCHED,严禁执行本脚本(Kingbase 将抛出 already an identity column 错误)。
+--
+-- 环境数据安全约束:
+-- - 本脚本仅添加 Identity 特性,默认从 1 开始;
+-- - 若当前 gen_table 为空表 (row_count = 0),执行后直接安全;
+-- - 若当前 gen_table 已存在历史元数据 (row_count > 0),执行后必须通过 003 脚本核对 Sequence 对齐状态;
+-- - 严禁 DROP 表、重建表或清空 Generator 元数据。
+-- ==============================================================================
+
+ALTER TABLE gen_table
+ALTER COLUMN table_id
+ADD GENERATED BY DEFAULT AS IDENTITY;
diff --git a/RuoYi-Vue/sql/generator/kingbase/002b_gen_table_column_identity_patch.sql b/RuoYi-Vue/sql/generator/kingbase/002b_gen_table_column_identity_patch.sql
new file mode 100644
index 000000000..7ea4c9f7c
--- /dev/null
+++ b/RuoYi-Vue/sql/generator/kingbase/002b_gen_table_column_identity_patch.sql
@@ -0,0 +1,22 @@
+-- ==============================================================================
+-- 002b_gen_table_column_identity_patch.sql
+-- Generator Kingbase Identity 独立补丁 B: gen_table_column.column_id
+--
+-- 变更目标:
+-- 为 public.gen_table_column.column_id 添加 GENERATED BY DEFAULT AS IDENTITY
+--
+-- 执行准入前置条件(强制要求):
+-- 1. 必须先执行 001_generator_identity_precheck.sql;
+-- 2. 仅当 Precheck 判定结果为 CASE_1_BOTH_NEED_PATCH 或 CASE_3_ONLY_COLUMN_NEEDS_PATCH 时方可执行;
+-- 3. 若 column_id 已为 ALREADY_PATCHED,严禁执行本脚本(Kingbase 将抛出 already an identity column 错误)。
+--
+-- 环境数据安全约束:
+-- - 本脚本仅添加 Identity 特性,默认从 1 开始;
+-- - 若当前 gen_table_column 为空表 (row_count = 0),执行后直接安全;
+-- - 若当前 gen_table_column 已存在历史元数据 (row_count > 0),执行后必须通过 003 脚本核对 Sequence 对齐状态;
+-- - 严禁 DROP 表、重建表或清空 Generator 元数据。
+-- ==============================================================================
+
+ALTER TABLE gen_table_column
+ALTER COLUMN column_id
+ADD GENERATED BY DEFAULT AS IDENTITY;
diff --git a/RuoYi-Vue/sql/generator/kingbase/003_generator_identity_verify.sql b/RuoYi-Vue/sql/generator/kingbase/003_generator_identity_verify.sql
new file mode 100644
index 000000000..1f57a16db
--- /dev/null
+++ b/RuoYi-Vue/sql/generator/kingbase/003_generator_identity_verify.sql
@@ -0,0 +1,146 @@
+-- ==============================================================================
+-- 003_generator_identity_verify.sql
+-- Generator Kingbase Identity 验证只读脚本 (增强版: 含 Sequence 对齐安全核验)
+--
+-- 功能:只读验证 gen_table 与 gen_table_column 的 Identity 状态及 Sequence 安全性
+-- 验证维度:
+-- 1. 列 Identity 属性配置:attidentity 精确等于 'd'
+-- 2. Sequence 存在性:gen_table_table_id_seq / gen_table_column_column_id_seq 均为 'S'
+-- 3. Sequence 依赖关系:sys_depend 中记录类型为 'i' (internal identity dependency)
+-- 4. Sequence 对齐安全位:下一个分配 ID 必须严格大于现有 MAX(id) (或空表 SAFE)
+-- 安全说明:纯只读查询,无任何 DDL / DML / nextval / setval 副作用
+-- ==============================================================================
+
+-- 1. 验证列级别 Identity 配置
+SELECT
+ c.relname AS table_name,
+ a.attname AS column_name,
+ a.attidentity AS attidentity,
+ CASE
+ WHEN a.attidentity = 'd' THEN 'PASS (GENERATED BY DEFAULT AS IDENTITY)'
+ ELSE 'FAIL (ATTIDENTITY_NOT_D)'
+ END AS identity_check
+FROM sys_class c
+JOIN sys_attribute a ON a.attrelid = c.oid
+JOIN sys_namespace n ON n.oid = c.relnamespace
+WHERE n.nspname = 'public'
+ AND ((c.relname = 'gen_table' AND a.attname = 'table_id')
+ OR (c.relname = 'gen_table_column' AND a.attname = 'column_id'))
+ORDER BY c.relname, a.attname;
+
+-- 2. 验证 Sequence 存在性与类别
+SELECT
+ c.relname AS sequence_name,
+ c.relkind AS relkind,
+ CASE
+ WHEN c.relkind = 'S' THEN 'PASS (SEQUENCE_EXISTS)'
+ ELSE 'FAIL (NOT_A_SEQUENCE)'
+ END AS sequence_check
+FROM sys_class c
+JOIN sys_namespace n ON n.oid = c.relnamespace
+WHERE n.nspname = 'public'
+ AND c.relname IN ('gen_table_table_id_seq', 'gen_table_column_column_id_seq')
+ORDER BY c.relname;
+
+-- 3. 验证 Sequence 依赖关系 (deptype = 'i')
+SELECT
+ s.relname AS sequence_name,
+ t.relname AS target_table,
+ a.attname AS target_column,
+ d.deptype AS dependency_type,
+ CASE
+ WHEN d.deptype = 'i' THEN 'PASS (INTERNAL_IDENTITY_DEPENDENCY)'
+ ELSE 'FAIL (INVALID_DEPENDENCY_TYPE)'
+ END AS dependency_check
+FROM sys_depend d
+JOIN sys_class s ON s.oid = d.objid
+JOIN sys_class t ON t.oid = d.refobjid
+JOIN sys_attribute a ON a.attrelid = d.refobjid AND a.attnum = d.refobjsubid
+JOIN sys_namespace n ON n.oid = t.relnamespace
+WHERE n.nspname = 'public'
+ AND t.relname IN ('gen_table', 'gen_table_column')
+ AND a.attname IN ('table_id', 'column_id')
+ORDER BY t.relname, a.attname;
+
+-- 4. 验证 Sequence 当前位置与已有 MAX(id) 对齐安全性 (只读)
+SELECT
+ 'gen_table' AS table_name,
+ 'table_id' AS column_name,
+ t.row_count,
+ t.max_id AS existing_max_id,
+ s.last_value::bigint AS sequence_last_value,
+ s.is_called,
+ CASE
+ WHEN t.row_count = 0 THEN 'EMPTY_TABLE_SAFE'
+ WHEN (CASE WHEN s.is_called THEN s.last_value::bigint + 1 ELSE s.last_value::bigint END) > t.max_id THEN 'SAFE'
+ ELSE 'UNSAFE (SEQUENCE_BEHIND_OR_EQUAL_MAX_ID)'
+ END AS seq_alignment_status
+FROM (SELECT COUNT(*) AS row_count, COALESCE(MAX(table_id), 0) AS max_id FROM gen_table) t,
+ gen_table_table_id_seq s
+UNION ALL
+SELECT
+ 'gen_table_column' AS table_name,
+ 'column_id' AS column_name,
+ c.row_count,
+ c.max_id AS existing_max_id,
+ s.last_value::bigint AS sequence_last_value,
+ s.is_called,
+ CASE
+ WHEN c.row_count = 0 THEN 'EMPTY_TABLE_SAFE'
+ WHEN (CASE WHEN s.is_called THEN s.last_value::bigint + 1 ELSE s.last_value::bigint END) > c.max_id THEN 'SAFE'
+ ELSE 'UNSAFE (SEQUENCE_BEHIND_OR_EQUAL_MAX_ID)'
+ END AS seq_alignment_status
+FROM (SELECT COUNT(*) AS row_count, COALESCE(MAX(column_id), 0) AS max_id FROM gen_table_column) c,
+ gen_table_column_column_id_seq s;
+
+-- 5. 总体综合判定 (包含属性配置、序列存在、依赖关系及 Sequence 对齐安全)
+WITH identity_summary AS (
+ SELECT count(*) AS id_cnt
+ FROM sys_class c
+ JOIN sys_attribute a ON a.attrelid = c.oid
+ JOIN sys_namespace n ON n.oid = c.relnamespace
+ WHERE n.nspname = 'public'
+ AND ((c.relname = 'gen_table' AND a.attname = 'table_id')
+ OR (c.relname = 'gen_table_column' AND a.attname = 'column_id'))
+ AND a.attidentity = 'd'
+),
+seq_summary AS (
+ SELECT count(*) AS seq_cnt
+ FROM sys_class c
+ JOIN sys_namespace n ON n.oid = c.relnamespace
+ WHERE n.nspname = 'public'
+ AND c.relname IN ('gen_table_table_id_seq', 'gen_table_column_column_id_seq')
+ AND c.relkind = 'S'
+),
+dep_summary AS (
+ SELECT count(*) AS dep_cnt
+ FROM sys_depend d
+ JOIN sys_class s ON s.oid = d.objid
+ JOIN sys_class t ON t.oid = d.refobjid
+ JOIN sys_attribute a ON a.attrelid = d.refobjid AND a.attnum = d.refobjsubid
+ JOIN sys_namespace n ON n.oid = t.relnamespace
+ WHERE n.nspname = 'public'
+ AND t.relname IN ('gen_table', 'gen_table_column')
+ AND a.attname IN ('table_id', 'column_id')
+ AND d.deptype = 'i'
+),
+seq_align AS (
+ SELECT
+ sum(CASE WHEN t.row_count = 0 OR (CASE WHEN s.is_called THEN s.last_value::bigint + 1 ELSE s.last_value::bigint END) > t.max_id THEN 1 ELSE 0 END) AS safe_cnt
+ FROM (
+ SELECT 'gen_table' AS tbl, COUNT(*) AS row_count, COALESCE(MAX(table_id), 0) AS max_id FROM gen_table
+ ) t, gen_table_table_id_seq s
+ UNION ALL
+ SELECT
+ sum(CASE WHEN c.row_count = 0 OR (CASE WHEN s.is_called THEN s.last_value::bigint + 1 ELSE s.last_value::bigint END) > c.max_id THEN 1 ELSE 0 END) AS safe_cnt
+ FROM (
+ SELECT 'gen_table_column' AS tbl, COUNT(*) AS row_count, COALESCE(MAX(column_id), 0) AS max_id FROM gen_table_column
+ ) c, gen_table_column_column_id_seq s
+)
+SELECT
+ CASE
+ WHEN i.id_cnt = 2 AND s.seq_cnt = 2 AND d.dep_cnt = 2 AND (SELECT sum(safe_cnt) FROM seq_align) = 2
+ THEN 'VERIFY: PASS (所有 Identity、Sequence、依赖关系与序列对齐安全核验一致通过)'
+ ELSE 'VERIFY: FAIL (存在核验未达标或 Sequence 落后风险,详情见分项输出)'
+ END AS overall_verify_result
+FROM identity_summary i, seq_summary s, dep_summary d;
diff --git a/RuoYi-Vue/sql/generator/kingbase/README.md b/RuoYi-Vue/sql/generator/kingbase/README.md
new file mode 100644
index 000000000..01998d32d
--- /dev/null
+++ b/RuoYi-Vue/sql/generator/kingbase/README.md
@@ -0,0 +1,79 @@
+# Kingbase Generator Identity 基础设施补丁
+
+## 1. 补丁目标
+解决 RuoYi 代码生成器(Generator)在 KingbaseES 数据库下执行表结构导入(`importGenTable`)时,因 `gen_table.table_id` 和 `gen_table_column.column_id` 缺失自增/Identity 属性,导致 `useGeneratedKeys="true"` 回填失败并引发主键冲突(Duplicate key violation)的运行时兼容性问题。
+
+## 2. 补丁范围与安全红线
+- **涉及对象**:严格仅限 `public.gen_table.table_id` 与 `public.gen_table_column.column_id`。
+- **安全红线**:
+ - 严禁修改 21 张 `train_*` 业务表;
+ - 严禁修改 `sys_*` 系统/权限/字典表;
+ - 严禁 DROP 表、重建表或清空/截断 Generator 历史元数据;
+ - 严禁在未做 Precheck 判定前盲目全量执行 Patch。
+
+## 3. 文件清单
+
+| 文件名 | 类型 | 说明 |
+| :--- | :---: | :--- |
+| `001_generator_identity_precheck.sql` | 只读探测 | 检查两列 Identity 配置、现有数据量及全局 Case 场景。 |
+| `002a_gen_table_identity_patch.sql` | DDL 补丁 | 仅为 `gen_table.table_id` 添加 `GENERATED BY DEFAULT AS IDENTITY`。 |
+| `002b_gen_table_column_identity_patch.sql` | DDL 补丁 | 仅为 `gen_table_column.column_id` 添加 `GENERATED BY DEFAULT AS IDENTITY`。 |
+| `003_generator_identity_verify.sql` | 只读验证 | 综合校验列属性、Sequence 存在、依赖关系及 Sequence 对齐安全性。 |
+
+---
+
+## 4. 四种 Partial / Full 执行决策矩阵
+
+根据 `001_generator_identity_precheck.sql` 查询 4 返回的 `precheck_scenario_verdict`,严格按以下矩阵执行:
+
+| 场景编号 | Precheck 判定结果 | 执行动作 |
+| :--- | :--- | :--- |
+| **Scenario A** | `CASE_1_BOTH_NEED_PATCH`
(两列均缺失 Identity) | 1. 执行 `002a_gen_table_identity_patch.sql`
2. 执行 `002b_gen_table_column_identity_patch.sql`
3. 执行 `003_generator_identity_verify.sql` |
+| **Scenario B** | `CASE_2_BOTH_ALREADY_PATCHED`
(两列均已配置 Identity) | **严禁执行任何 Patch!**
直接执行 `003_generator_identity_verify.sql` 复核。 |
+| **Scenario C** | `CASE_3_ONLY_COLUMN_NEEDS_PATCH`
(仅 `column_id` 缺失) | **严禁执行 002a!**
1. 仅执行 `002b_gen_table_column_identity_patch.sql`
2. 执行 `003_generator_identity_verify.sql` |
+| **Scenario D** | `CASE_4_ONLY_TABLE_NEEDS_PATCH`
(仅 `table_id` 缺失) | **严禁执行 002b!**
1. 仅执行 `002a_gen_table_identity_patch.sql`
2. 执行 `003_generator_identity_verify.sql` |
+
+---
+
+## 5. 数据环境分类与 Sequence 对齐要求
+
+### 5.1 Case A:Generator 元数据为空(0 rows,全新环境)
+- `001` 预检中 `env_type` 为 `EMPTY_METADATA_ENV`;
+- 执行 Patch 后,Kingbase 自动生成的 Sequence 从 1 开始分配;
+- 执行 `003` 核验,Sequence 对齐状态将显示 `EMPTY_TABLE_SAFE`,可直接投入使用。
+
+### 5.2 Case B:Generator 元数据已存在(已有历史导入数据)
+- `001` 预检中 `env_type` 为 `EXISTING_METADATA_ENV`;
+- **核心风险**:Kingbase `ADD GENERATED BY DEFAULT AS IDENTITY` 在已有数据环境下默认从 1 开始分配,**不宣称自动对齐已有数据 MAX(id)**!
+- **操作要求**:
+ 1. 执行对应补丁后,**必须立即执行 `003_generator_identity_verify.sql`**;
+ 2. 观察验证输出中的 `seq_alignment_status`:
+ - 若为 `SAFE`:表明 sequence 位置已超前于现有数据(例如已有试点导入推进了序列),可直接使用;
+ - 若为 `UNSAFE`:表明 sequence 当前位置落后或等于现有主键,**绝对禁止直接继续 Generator Import**!
+ 3. **Sequence 对齐专项步骤(需 DBA 确认并在维护窗口执行)**:
+ 针对落后的序列,使用 Kingbase 兼容的管理语法调整序列游标:
+ ```sql
+ -- 示例:对齐 gen_table sequence
+ SELECT setval('gen_table_table_id_seq', (SELECT COALESCE(MAX(table_id), 0) + 1 FROM gen_table), false);
+ -- 示例:对齐 gen_table_column sequence
+ SELECT setval('gen_table_column_column_id_seq', (SELECT COALESCE(MAX(column_id), 0) + 1 FROM gen_table_column), false);
+ ```
+ 4. 重新执行 `003_generator_identity_verify.sql`,确认全部输出 `SAFE` 且最终结果为 `VERIFY: PASS` 后,方可开放表导入功能。
+
+---
+
+## 6. 执行命令示例(无真实凭据)
+
+```bash
+# 步骤 1: 预检并确认 Scenario
+ksql -h -p -U -d -f 001_generator_identity_precheck.sql
+
+# 步骤 2: 根据 Precheck 决策矩阵有选择地执行对应补丁
+# 仅当命中 Scenario A 或 D 时:
+ksql -h -p -U -d -f 002a_gen_table_identity_patch.sql
+# 仅当命中 Scenario A 或 C 时:
+ksql -h -p -U -d -f 002b_gen_table_column_identity_patch.sql
+
+# 步骤 3: 严格复核验证
+ksql -h -p -U -d -f 003_generator_identity_verify.sql
+```
diff --git a/docs/generator-v2/01_kingbase_import_identity_patch.md b/docs/generator-v2/01_kingbase_import_identity_patch.md
new file mode 100644
index 000000000..9128eb646
--- /dev/null
+++ b/docs/generator-v2/01_kingbase_import_identity_patch.md
@@ -0,0 +1,202 @@
+# Generator 基础设施补丁 — Kingbase Import Identity 修复记录
+
+本文档详细记录 RuoYi Generator 代码生成器在 KingbaseES 数据库环境下的核心运行时兼容性问题排查、补丁设计、安全加固与验证全过程。
+
+---
+
+## 1. 问题背景
+
+RailwaySystem 后台基于 RuoYi-Vue 架构改造,数据库由 MySQL 迁移至国产 KingbaseES (V8R6 / PostgreSQL 语法体系)。代码生成器(`ruoyi-generator` 模块)用于读取数据库系统元数据、导入数据表配置并自动生成前端 Vue 与后端 Java/MyBatis 代码。
+
+在 Generator 元数据体系中,包含两张核心表:
+- `gen_table`:存储已导入代码生成的表元数据;
+- `gen_table_column`:存储表关联的列元数据。
+
+在最初从 MySQL 初始化表结构至 Kingbase 时,这两张表的自增主键定义未能正确映射为 Kingbase 标准的 Identity 列。
+
+---
+
+## 2. 第一次真实 Import 如何暴露问题
+
+在推进首个业务模块试点开发(**Teacher Pilot**,教师主数据模块)期间,需要通过前端代码生成管理界面(`/tool/gen`)调用“导入表(Import Table)”功能将 `train_teacher` 表导入至 Generator 配置库中。
+
+当点击导入并提交时,后端触发了 `GenTableServiceImpl.importGenTable` 调用。此时服务端直接抛出数据库异常,表导入操作失败,导致后续代码生成流程无法继续。
+
+---
+
+## 3. 错误现象
+
+后端日志与数据库抛出类似如下的主键冲突与唯一约束冲突异常:
+
+```text
+### Error updating database. Cause: com.kingbase8.util.KSQLException: ERROR: duplicate key value violates unique constraint "gen_table_pkey"
+ Detail: Key (table_id)=(0) already exists.
+### The error may exist in URL [jar:file:.../ruoyi-generator.jar!/mapper/generator/GenTableMapper.xml]
+### The error may involve com.ruoyi.generator.mapper.GenTableMapper.insertGenTable-Inline
+### The error occurred while setting parameters
+### SQL: insert into gen_table ( table_name, table_comment, class_name, ... ) values ( ?, ?, ?, ... )
+```
+
+对于 `gen_table_column`,同样在批量插入字段元数据时出现所有字段的 `column_id` 均被赋值为默认值 `0`,从而连续抛出主键冲突。
+
+---
+
+## 4. 根因分析
+
+1. **MyBatis 配置与运行时预期**:
+ `GenTableMapper.xml` 与 `GenTableColumnMapper.xml` 中的插入语句均配置了:
+ ```xml
+
+
+ ```
+ RuoYi 的应用层期望数据库能够在插入记录时自动生成唯一递增主键,并通过 JDBC 驱动的 `getGeneratedKeys` 返回该主键值并回填至 Java 实体对象的 `tableId` / `columnId`。
+
+2. **原始 MySQL 建表定义**:
+ 在 `RuoYi-Vue/sql/ry_20250522.sql` 中,原始表结构为:
+ ```sql
+ CREATE TABLE gen_table (
+ table_id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
+ ...
+ PRIMARY KEY (table_id)
+ );
+ CREATE TABLE gen_table_column (
+ column_id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
+ ...
+ PRIMARY KEY (column_id)
+ );
+ ```
+
+3. **Kingbase 结构缺失 Identity / Sequence**:
+ 在早期导入 Kingbase 实例时,由于 KingbaseES 不支持 MySQL 方言的 `AUTO_INCREMENT` 关键字,该列在创建时仅退化为 `BIGINT NOT NULL`,未配置 `GENERATED BY DEFAULT AS IDENTITY`,也未创建对应的自增序列(Sequence)。
+ 由于 INSERT 语句未指定主键值,在某些兼容模式下默认填入 `0`,第二次插入必然导致唯一主键冲突。
+
+4. **定位结论**:
+ 本问题属于典型的 **Generator 运行时基础设施兼容性缺陷(Generator Runtime Compatibility Bug)**,与业务层 Database V2 数据模型无关。
+
+---
+
+## 5. 补丁文件拆分与核心 DDL
+
+为了避免局部补丁状态(Partial Patch)下执行发生冲突,补丁拆分为两个独立文件:
+
+### 5.1 `002a_gen_table_identity_patch.sql`
+```sql
+ALTER TABLE gen_table
+ALTER COLUMN table_id
+ADD GENERATED BY DEFAULT AS IDENTITY;
+```
+
+### 5.2 `002b_gen_table_column_identity_patch.sql`
+```sql
+ALTER TABLE gen_table_column
+ALTER COLUMN column_id
+ADD GENERATED BY DEFAULT AS IDENTITY;
+```
+
+执行后,KingbaseES 底层会自动创建并维护两个关联序列:
+- `gen_table_table_id_seq`
+- `gen_table_column_column_id_seq`
+
+---
+
+## 6. Precheck(预检)与 Partial Patch 安全机制
+
+### 6.1 Partial Patch Safety(局部补丁状态安全)
+在实际运维过程中,数据库可能处于以下四种状态之一:
+1. **Case 1 (`CASE_1_BOTH_NEED_PATCH`)**:两列均未配置 Identity;
+2. **Case 2 (`CASE_2_BOTH_ALREADY_PATCHED`)**:两列均已配置 Identity;
+3. **Case 3 (`CASE_3_ONLY_COLUMN_NEEDS_PATCH`)**:`table_id` 已修复,但 `column_id` 未修复;
+4. **Case 4 (`CASE_4_ONLY_TABLE_NEEDS_PATCH`)**:`column_id` 已修复,但 `table_id` 未修复。
+
+若在 Case 3 下全量执行整脚本,Kingbase 执行 `gen_table` ALTER 时将直接报错 `column "table_id" of relation "gen_table" is already an identity column` 并中断退出。
+
+**解决方案**:
+- `001_generator_identity_precheck.sql` 会直接输出全局 Case 判定;
+- 补丁拆分为 `002a` 与 `002b`,根据 Precheck 的判定选择性执行,实现精准幂等与局部安全性。
+
+---
+
+## 7. Existing Metadata Safety 与 Sequence Alignment
+
+### 7.1 核心原则
+> **Identity 属性存在 ≠ Sequence 一定适合下一次 Insert**
+
+在执行 `ALTER TABLE ... ADD GENERATED BY DEFAULT AS IDENTITY` 时:
+- **空表环境(0 rows)**:默认 Sequence `start_value = 1`,下一次插入分配 ID 为 1,天然安全;
+- **已有数据环境(已存在历史元数据)**:
+ - Kingbase `ADD IDENTITY` 默认创建从 1 开始的 Sequence,**不宣称自动对齐已有数据的 MAX(id)**;
+ - 若直接执行 Insert,Sequence 将尝试从 1 开始分配,如果已有数据包含 `id = 1`,将再次引发主键冲突!
+
+### 7.2 Sequence 对齐机制(Sequence Alignment)
+对于非空表环境,执行 Patch 后必须通过 Verify 脚本校验序列游标:
+- 计算表达式:`next_id = (CASE WHEN is_called THEN last_value + 1 ELSE last_value END)`
+- 若 `next_id > MAX(existing_id)`,判定为 `SAFE`;
+- 若 `next_id <= MAX(existing_id)`,判定为 `UNSAFE`,必须由 DBA 执行专项对齐脚本:
+ ```sql
+ -- 同步 Sequence 游标至当前最大值之后
+ SELECT setval('gen_table_table_id_seq', (SELECT COALESCE(MAX(table_id), 0) + 1 FROM gen_table), false);
+ SELECT setval('gen_table_column_column_id_seq', (SELECT COALESCE(MAX(column_id), 0) + 1 FROM gen_table_column), false);
+ ```
+
+---
+
+## 8. Verify(复核验证)
+
+执行只读复核脚本 `003_generator_identity_verify.sql`,执行四大维度的综合核验:
+1. **核验列属性**:确认两列 `attidentity = 'd'`;
+2. **核验 Sequence 存在性**:确认关联序列存在且 `relkind = 'S'`;
+3. **核验依赖关系**:确认 `sys_depend.deptype = 'i'`(内部生命周期绑定);
+4. **核验 Sequence 对齐安全性**:确认两表的 Sequence 处于 `SAFE` 或 `EMPTY_TABLE_SAFE` 状态;
+5. **最终判定**:四项维度全通过输出 `VERIFY: PASS`。
+
+---
+
+## 9. Rollback 风险说明
+
+若因特殊场景需要撤销该修改,语法为:
+```sql
+ALTER TABLE gen_table ALTER COLUMN table_id DROP IDENTITY IF EXISTS;
+ALTER TABLE gen_table_column ALTER COLUMN column_id DROP IDENTITY IF EXISTS;
+```
+
+### 回滚风险评估
+1. **Generator 瘫痪**:一旦移除 Identity,Generator 将立即恢复至无法导入表的故障状态;
+2. **元数据序列断裂**:若已有元数据记录,回滚后再配置可能造成序列重新错位;
+3. **结论**:该补丁作为 RuoYi 适配 Kingbase 必需的基础设施配置,**严禁回滚**;任何环境初始化后均应持久化保留此配置。
+
+---
+
+## 10. 新环境部署要求
+
+在搭建全新 Kingbase 部署环境或自动化 CI/CD 环境时:
+1. 执行若依基础建表脚本;
+2. 执行预检:
+ ```bash
+ ksql -h -p -U -d -f RuoYi-Vue/sql/generator/kingbase/001_generator_identity_precheck.sql
+ ```
+3. 按照决策矩阵执行对应补丁(空表全新环境直接依次执行 `002a` 和 `002b`);
+4. 执行复核验证并确认输出 `VERIFY: PASS`:
+ ```bash
+ ksql -h -p -U -d -f RuoYi-Vue/sql/generator/kingbase/003_generator_identity_verify.sql
+ ```
+
+---
+
+## 11. 与 Database V2 无关性声明
+
+- **范围隔离**:本修复纯属 Generator 工具层基础设施兼容补丁,仅修改 `public.gen_table` 与 `public.gen_table_column` 两张系统级代码生成支撑表的主键属性;
+- **业务无关**:零改动 21 张 `train_*` 业务模型表;零改动任何业务枚举、外键约束与数据字典;
+- **版本独立**:补丁存放于 `RuoYi-Vue/sql/generator/kingbase/`,独立于业务迁移目录 `RuoYi-Vue/sql/train/v2/`。
+
+---
+
+## 12. Teacher Pilot 验证事实与当前共享库核验
+
+- 在 Teacher Pilot(`feat/issue-01-01-teacher`)开发期间,共享 Kingbase 数据库已应用该 DDL 修复;
+- 真实导入测试:调用 Generator 导入 `train_teacher` 表,`gen_table` 成功生成非零递增主键(`table_id = 1`),同时其 16 个字段成功写入 `gen_table_column`(`column_id = 1..16`);
+- 代码生成测试:成功基于导入元数据生成教师主数据相关 Controller、Service、Mapper、Domain 及前端 Vue 页面,未产生任何主键冲突;
+- **当前共享库只读核验数据(实测)**:
+ - `gen_table`: `row_count = 1`, `max_id = 1`, `sequence last_value = 2`, `is_called = true`,下一个分配值为 3 > 1,状态为 `SAFE`;
+ - `gen_table_column`: `row_count = 16`, `max_id = 16`, `sequence last_value = 32`, `is_called = true`,下一个分配值为 33 > 16,状态为 `SAFE`;
+ - 属性 `attidentity = 'd'`,序列依赖均为 `deptype = 'i'`;
+ - 复核脚本输出:`VERIFY: PASS (所有 Identity、Sequence、依赖关系与序列对齐安全核验一致通过)`。