datai/docs/skill/phase4-database-schema.md
Kris b7163d555b feat: 实现动态数据源延迟加载功能 (2026-01-21-001)
## 功能概述
- 实现动态数据源的延迟加载机制,支持应用启动时只加载主库,从库按需动态加载和切换
- 从库配置存储在主库中,支持运行时灵活切换从库库名
- 使用现有的 @DataSource 注解进行数据源切换,业务代码无需修改

## 新增功能
- 动态数据源管理接口 IDynamicDataSourceManager
- 动态数据源服务接口 IDynamicDataSourceService
- 动态数据源服务实现 DynamicDataSourceServiceImpl
- 数据源管理控制器 DatasourceController
- 数据源配置表 sys_datasource_config

## 新增文档
- 需求文档: docs/requirements/2026-01-21-001-动态数据源延迟加载.md
- 设计文档: docs/design/2026-01-21-001-动态数据源延迟加载设计.md
- 决策记录: docs/decisions/2026-01-21-001-ADR-动态数据源延迟加载.md
- SQL 脚本: docs/sql/2026-01-21-001-sys_datasource_config.sql
- 提示词: docs/prompts/2026-01-21-001-动态数据源延迟加载代码生成提示词.md
- 会话记录: docs/sessions/2026-01-21-001-session.md
- 变更日志: docs/changelog/2026-01-21-001-changelog.md
- 复盘文档: docs/retros/2026-01-21-001-retro.md
- API 文档: docs/api-docs/2026-01-21-001-api.md
- 根目录变更日志: CHANGELOG.md

## 修改功能
- 扩展 DataSourceManager 类,添加动态数据源管理方法
- 扩展 SysDatasourceConfigMapper 接口,添加 selectSysDatasourceConfigByDsName 方法
- 更新项目索引和 Authentication.canvas

## 修复问题
- 修复循环依赖问题:创建 IDynamicDataSourceManager 接口解决 datai-system 和 datai-framework 互相依赖
- 修复导入错误:删除 DynamicDataSourceServiceImpl 中未使用的导入
- 修复异常处理:将 setFilters() 调用移到 try-catch 块内

## API 接口
- POST /system/datasource/loadSlave - 加载从库数据源
- POST /system/datasource/switchSlave/{dbName} - 切换从库库名
- GET /system/datasource/getSlaveConfig - 获取从库配置
- POST /system/datasource/switch/{dsName} - 切换数据源
- DELETE /system/datasource/{dsName} - 移除数据源
2026-01-21 18:24:24 +08:00

528 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 阶段 4数据库结构生成技能书
## A. 元数据 (Metadata)
**name**: `phase4-database-schema`
**description**: 在 Datai 项目中,基于已创建的设计文档和决策记录,分析需求是否涉及数据库变更,生成标准化的 SQL 脚本,并更新索引和会话记录。此技能确保数据库变更的可追溯性和准确性。
---
## B. 触发与定位 (Triggers & Scope)
### 触发关键词
当用户输入包含以下关键词时,必须觉醒此技能:
- "数据库结构"、"SQL 脚本"、"DDL"
- "数据库变更"、"表设计"、"字段设计"
- "进入阶段 4"、"下一阶段"
- "数据库"、"表"、"字段"
### 触发场景
- 用户确认阶段 3 完成,要求进入阶段 4
- 用户要求生成 SQL 脚本
- 用户询问如何设计数据库结构
- 用户提到"按照项目规则"或"SSOT 流程"进行数据库设计
### 操作路径
此技能涉及以下文件和目录的操作:
- **读取**: `docs/design/YYYY-MM-DD-00X-设计名.md` (阶段 2 创建的设计文档)
- **创建**: `docs/sql/YYYY-MM-DD-00X-数据库名.sql`
- **更新**: `docs/index.md`
- **更新**: `docs/design/YYYY-MM-DD-00X-设计名.md` (添加 SQL 脚本引用)
- **更新**: `docs/sessions/YYYY-MM-DD-00X-session.md`
- **读取**: `.trae/rules/project_rules.md` (项目规则)
- **读取**: `docs/Prompt/0004-单一真源文档驱动架构师.md` (SSOT 架构师提示词)
### SSOT 依赖
必须参考以下"唯一真源"
- [设计文档](file:///d:\idea_demo\datai\docs\design\YYYY-MM-DD-00X-设计名.md) - 阶段 2 创建的设计文档
- [project_rules.md](file:///d:\idea_demo\datai\.trae\rules\project_rules.md) - 项目规则和阶段定义
- [0004-单一真源文档驱动架构师.md](file:///d:\idea_demo\datai\docs\Prompt\0004-单一真源文档驱动架构师.md) - SSOT 架构师提示词
- `docs/sql/` 目录下的现有 SQL 脚本(作为格式参考)
- 若依框架的数据库规范(如表前缀、字段命名等)
---
## C. 核心指令集 (Instructions)
### 架构约束
#### 1. 脚本命名规范(强制)
- 必须使用格式:`YYYY-MM-DD-00X-数据库名.sql`
- `YYYY-MM-DD`:当前日期(如 2026-01-21
- `00X`:需求编号(与阶段 1-3 保持一致)
- `数据库名`:简洁描述,使用中文或英文,如"user-login"、"订单表"
- **严禁**使用无意义的文件名
#### 2. 脚本内容约束(强制)
SQL 脚本必须包含以下内容:
- 脚本说明(-- 注释)
- 建表语句CREATE TABLE
- 修改语句ALTER TABLE如果需要
- 索引语句CREATE INDEX如果需要
- 数据插入语句INSERT INTO如果需要如数据字典
- 脚本结束标识
#### 3. 数据库规范约束(强制)
- **表命名**:使用小写字母,单词之间用下划线分隔,如 `sys_user`
- **字段命名**:使用小写字母,单词之间用下划线分隔,如 `user_name`
- **字段类型**
- 字符串VARCHAR(长度),如 `VARCHAR(30)`
- 数字INT, BIGINT, DECIMAL(精度, 小数位数),如 `BIGINT`, `DECIMAL(10, 2)`
- 日期DATETIME, DATE, TIMESTAMP`DATETIME`
- **主键约束**:每个表必须有主键,命名格式:`PRIMARY KEY (id)`
- **外键约束**:命名格式:`FK_表名_关联表名`,如 `FK_sys_user_sys_dept`
- **索引约束**:命名格式:`IDX_表名_字段名`,如 `IDX_sys_user_user_name`
- **注释**:每个表和字段必须有注释,使用 `COMMENT` 关键字
#### 4. 条件约束(强制)
- 必须分析需求是否涉及数据库变更
- 如果不涉及,跳过此阶段,直接进入阶段 5
- 如果涉及,识别需要变更的表和字段
#### 5. 索引更新约束(强制)
- 必须在生成 SQL 脚本后立即更新 `docs/index.md`
- 必须更新设计文档,添加 SQL 脚本引用
- 采用增量更新策略,**严禁**删除现有内容
- 索引链接格式:`[文档名](./相对路径/文件名.md)`
- 必须在 `docs/index.md` 中添加到"SQL 脚本"部分
#### 6. 会话记录约束(强制)
- 必须更新 `docs/sessions/YYYY-MM-DD-00X-session.md`
- 必须更新当前阶段为"阶段 4数据库结构生成"
- 必须记录是否涉及数据库变更
- 必须记录 SQL 脚本链接
### 业务逻辑 SOP标准操作流程
#### 步骤 1需求分析Let's think step by step
在生成 SQL 脚本前,必须执行以下分析:
1. **分析需求是否涉及数据库变更**
- 读取阶段 2 创建的设计文档
- 检查设计文档中的"数据模型"部分
- 检查是否需要创建新表
- 检查是否需要修改现有表
- 检查是否需要添加索引
- 检查是否需要插入初始数据(如数据字典)
2. **如果不涉及,跳过此阶段**
- 记录到会话记录中
- 直接进入阶段 5
3. **如果涉及,识别需要变更的表和字段**
- 识别需要创建的新表
- 识别需要修改的现有表
- 识别需要添加的字段
- 识别需要修改的字段
- 识别需要删除的字段
- 识别需要添加的索引
- 识别需要插入的初始数据
#### 步骤 2生成 SQL 脚本
1. **确定脚本路径**
- 路径:`docs/sql/YYYY-MM-DD-00X-数据库名.sql`
- 使用 Write 工具创建文件
- 确保目录存在(使用 LS 工具检查)
2. **编写脚本内容**
- **脚本说明**:使用 `--` 注释,说明脚本的用途、创建时间、创建人等
- **建表语句**
```sql
-- 创建用户表
CREATE TABLE `sys_user` (
`user_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`user_name` VARCHAR(30) NOT NULL COMMENT '用户名',
`password` VARCHAR(100) NOT NULL COMMENT '密码',
`dept_id` BIGINT NOT NULL COMMENT '部门ID',
`status` CHAR(1) NOT NULL DEFAULT '0' COMMENT '状态0正常 1停用',
`create_time` DATETIME NOT NULL COMMENT '创建时间',
`update_time` DATETIME NOT NULL COMMENT '更新时间',
PRIMARY KEY (`user_id`),
INDEX `IDX_sys_user_user_name` (`user_name`),
FOREIGN KEY (`dept_id`) REFERENCES `sys_dept` (`dept_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
```
- **修改语句**
```sql
-- 修改用户表,添加新字段
ALTER TABLE `sys_user` ADD COLUMN `email` VARCHAR(50) COMMENT '邮箱' AFTER `password`;
```
- **索引语句**
```sql
-- 为用户表添加索引
CREATE INDEX `IDX_sys_user_email` ON `sys_user` (`email`);
```
- **数据插入语句**
```sql
-- 插入数据字典
INSERT INTO `sys_dict_data` (`dict_type`, `dict_label`, `dict_value`, `status`) VALUES
('sys_user_status', '正常', '0', '0'),
('sys_user_status', '停用', '1', '0');
```
- **脚本结束标识**
```sql
-- 脚本执行完成
```
3. **脚本质量检查**
- 使用 Read 工具读取刚创建的脚本
- 检查是否符合脚本内容约束
- 检查是否符合数据库规范约束
- 检查 SQL 语法是否正确
- 检查表和字段注释是否完整
#### 步骤 3更新索引和设计文档
1. **读取现有索引**
- 使用 Read 工具读取 `docs/index.md`
- 找到"SQL 脚本"部分
- 如果不存在,则创建该部分
2. **添加新 SQL 脚本链接**
- 在"SQL 脚本"部分追加新脚本
- 格式:`- [SQL 脚本名](./sql/YYYY-MM-DD-00X-数据库名.sql) - [描述]`
- 示例:`- [用户登录功能-SQL 脚本](./sql/2026-01-21-001-user-login.sql) - 创建用户表和相关索引`
3. **更新设计文档**
- 使用 Read 工具读取设计文档
- 在"相关文档"部分添加 SQL 脚本引用
- 格式:`- [SQL 脚本](../sql/YYYY-MM-DD-00X-数据库名.sql)`
- 使用 Write 工具更新设计文档
4. **保存索引**
- 使用 Write 工具更新 `docs/index.md`
- **严禁**删除现有内容,只追加新内容
#### 步骤 4更新会话记录
1. **读取现有会话记录**
- 使用 Read 工具读取 `docs/sessions/YYYY-MM-DD-00X-session.md`
2. **更新阶段 4 信息**
- 更新"当前阶段"为"阶段 4数据库结构生成"
- 更新"阶段 4数据库结构生成"的状态为"已完成"
- 记录是否涉及数据库变更
- 添加生成的 SQL 脚本链接
- 记录关键数据库变更内容
3. **保存会话记录**
- 使用 Write 工具更新会话记录
#### 步骤 5确认与询问
1. **向用户确认**
- 显示 SQL 脚本的链接
- 询问:"SQL 脚本是否正确?"
- 询问:"是否进入下一阶段(提示词生成)?"
2. **等待用户反馈**
- 如果用户不满意,询问具体需要修改的地方
- 如果用户要求回退,执行回退机制(见错误陷阱部分)
- 如果用户确认,标记阶段 4 为已完成,准备进入阶段 5
### 工具调用
#### 必须使用的工具
1. **Read 工具**:读取现有文件
- 使用场景:读取设计文档、读取索引、读取会话记录
- 命令:`Read(file_path="d:\\idea_demo\\datai\\docs\\design\\2026-01-21-001-用户登录功能-设计.md")`
2. **Write 工具**:创建或更新文件
- 使用场景:生成 SQL 脚本、更新索引、更新设计文档、更新会话记录
- 命令:`Write(file_path="d:\\idea_demo\\datai\\docs\\sql\\2026-01-21-001-user-login.sql", content="...")`
3. **LS 工具**:检查目录是否存在
- 使用场景:创建脚本前检查 `docs/sql/` 目录
- 命令:`LS(path="d:\\idea_demo\\datai\\docs")`
#### 可选使用的工具
1. **SearchCodebase 工具**:搜索现有 SQL 脚本
- 使用场景:查找现有 SQL 脚本作为参考
- 命令:`SearchCodebase(information_request="查找 docs/sql 目录下的所有 SQL 脚本")`
2. **Glob 工具**:查找文件
- 使用场景:查找所有 SQL 脚本
- 命令:`Glob(pattern="docs/sql/*.sql")`
3. **TodoWrite 工具**:管理任务
- 使用场景:跟踪阶段执行进度
- 命令:`TodoWrite(todos=[...])`
---
## D. 错误陷阱与验证 (Anti-Patterns & Checklist)
### 常见错误Anti-Patterns
#### 错误 1不分析需求直接生成 SQL 脚本
**错误示例**
```
用户:进入阶段 4
AI直接生成 SQL 脚本,不分析需求是否涉及数据库变更
```
**正确示例**
```
用户:进入阶段 4
AI让我先分析需求是否涉及数据库变更...
AI读取设计文档检查数据模型部分...
AI如果涉及数据库变更生成 SQL 脚本...
AI如果不涉及跳过此阶段直接进入阶段 5...
```
#### 错误 2SQL 脚本缺少注释
**错误示例**
```sql
CREATE TABLE sys_user (
user_id BIGINT NOT NULL AUTO_INCREMENT,
user_name VARCHAR(30) NOT NULL,
password VARCHAR(100) NOT NULL,
PRIMARY KEY (user_id)
) ENGINE=InnoDB;
```
**问题**
- 缺少脚本说明
- 缺少表注释
- 缺少字段注释
**正确示例**
```sql
-- 用户登录功能 SQL 脚本
-- 创建时间2026-01-21
-- 创建人AI Assistant
-- 创建用户表
CREATE TABLE `sys_user` (
`user_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`user_name` VARCHAR(30) NOT NULL COMMENT '用户名',
`password` VARCHAR(100) NOT NULL COMMENT '密码',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
```
#### 错误 3SQL 语法错误
**错误示例**
```sql
CREATE TABLE sys_user (
user_id BIGINT NOT NULL AUTO_INCREMENT,
user_name VARCHAR(30) NOT NULL,
password VARCHAR(100) NOT NULL,
PRIMARY KEY (user_id)
INDEX IDX_sys_user_user_name (user_name)
) ENGINE=InnoDB;
```
**问题**
- 主键约束和索引约束之间缺少逗号
**正确示例**
```sql
CREATE TABLE sys_user (
user_id BIGINT NOT NULL AUTO_INCREMENT,
user_name VARCHAR(30) NOT NULL,
password VARCHAR(100) NOT NULL,
PRIMARY KEY (user_id),
INDEX IDX_sys_user_user_name (user_name)
) ENGINE=InnoDB;
```
#### 错误 4不遵循数据库规范
**错误示例**
```sql
CREATE TABLE SysUser (
UserId BIGINT NOT NULL AUTO_INCREMENT,
UserName VARCHAR(30) NOT NULL,
PRIMARY KEY (UserId)
) ENGINE=InnoDB;
```
**问题**
- 表名使用驼峰命名,不符合规范(应使用下划线分隔)
- 字段名使用驼峰命名,不符合规范(应使用下划线分隔)
**正确示例**
```sql
CREATE TABLE `sys_user` (
`user_id` BIGINT NOT NULL AUTO_INCREMENT,
`user_name` VARCHAR(30) NOT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB;
```
#### 错误 5不更新设计文档的 SQL 脚本引用
**错误示例**
```
AI生成 SQL 脚本
AI更新 docs/index.md
AI完成忘记更新设计文档
```
**正确示例**
```
AI生成 SQL 脚本
AI更新 docs/index.md
AI更新设计文档添加 SQL 脚本引用
AI完成
```
#### 错误 6不询问用户确认就进入下一阶段
**错误示例**
```
AI生成 SQL 脚本
AI进入阶段 5提示词生成未询问用户
```
**正确示例**
```
AI生成 SQL 脚本
AISQL 脚本已生成:[链接]
AISQL 脚本是否正确?
AI是否进入下一阶段提示词生成
```
### 验收清单Checklist
在完成阶段 4 前,必须检查以下项目:
#### 脚本完整性检查
- [ ] SQL 脚本已创建在 `docs/sql/` 目录下(如果涉及数据库变更)
- [ ] 脚本命名符合 `YYYY-MM-DD-00X-数据库名.sql` 格式
- [ ] 脚本包含脚本说明(注释)
- [ ] 脚本包含建表语句(如果需要)
- [ ] 脚本包含修改语句(如果需要)
- [ ] 脚本包含索引语句(如果需要)
- [ ] 脚本包含数据插入语句(如果需要)
- [ ] 脚本包含脚本结束标识
#### 脚本质量检查
- [ ] SQL 语法正确
- [ ] 表命名符合规范(小写字母,下划线分隔)
- [ ] 字段命名符合规范(小写字母,下划线分隔)
- [ ] 字段类型选择合理
- [ ] 每个表都有主键
- [ ] 每个表和字段都有注释
- [ ] 索引命名符合规范
- [ ] 外键命名符合规范
#### 条件检查
- [ ] 已分析需求是否涉及数据库变更
- [ ] 如果不涉及,已跳过此阶段,直接进入阶段 5
- [ ] 如果涉及,已识别需要变更的表和字段
#### 索引更新检查
- [ ] `docs/index.md` 已更新(如果涉及数据库变更)
- [ ] 新 SQL 脚本链接已添加到"SQL 脚本"部分
- [ ] 索引链接格式正确:`[文档名](./相对路径/文件名.md)`
- [ ] 索引更新采用增量策略,未删除现有内容
#### 设计文档更新检查
- [ ] 设计文档已更新(如果涉及数据库变更)
- [ ] 设计文档的"相关文档"部分已添加 SQL 脚本引用
- [ ] SQL 脚本链接格式正确:`[SQL 脚本](../sql/YYYY-MM-DD-00X-数据库名.sql)`
#### 会话记录更新检查
- [ ] 会话记录已更新
- [ ] 会话记录的"当前阶段"已更新为"阶段 4数据库结构生成"
- [ ] 会话记录的"阶段 4数据库结构生成"状态已更新为"已完成"
- [ ] 会话记录包含是否涉及数据库变更的记录
- [ ] 会话记录包含 SQL 脚本链接(如果涉及数据库变更)
- [ ] 会话记录包含关键数据库变更内容(如果涉及数据库变更)
#### 用户确认检查
- [ ] 已向用户显示 SQL 脚本链接(如果涉及数据库变更)
- [ ] 已询问用户"SQL 脚本是否正确?"(如果涉及数据库变更)
- [ ] 已询问用户"是否进入下一阶段?"
- [ ] 已等待用户反馈
#### 回退机制检查(如果需要)
- [ ] 如果用户不满意,已询问具体需要修改的地方
- [ ] 如果用户要求回退,已删除相关文档
- [ ] 如果用户要求回退,已撤销索引更新
- [ ] 如果用户要求回退,已撤销设计文档更新
- [ ] 如果用户要求回退,已更新会话记录
### Correct vs Incorrect 代码对比
#### Incorrect错误示例
```sql
CREATE TABLE SysUser (
UserId BIGINT NOT NULL AUTO_INCREMENT,
UserName VARCHAR(30) NOT NULL,
Password VARCHAR(100) NOT NULL,
PRIMARY KEY (UserId)
) ENGINE=InnoDB;
```
#### Correct正确示例
```sql
-- 用户登录功能 SQL 脚本
-- 创建时间2026-01-21
-- 创建人AI Assistant
-- 创建用户表
CREATE TABLE `sys_user` (
`user_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`user_name` VARCHAR(30) NOT NULL COMMENT '用户名',
`password` VARCHAR(100) NOT NULL COMMENT '密码',
`dept_id` BIGINT NOT NULL COMMENT '部门ID',
`status` CHAR(1) NOT NULL DEFAULT '0' COMMENT '状态0正常 1停用',
`create_time` DATETIME NOT NULL COMMENT '创建时间',
`update_time` DATETIME NOT NULL COMMENT '更新时间',
PRIMARY KEY (`user_id`),
INDEX `IDX_sys_user_user_name` (`user_name`),
FOREIGN KEY (`dept_id`) REFERENCES `sys_dept` (`dept_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
-- 插入用户状态数据字典
INSERT INTO `sys_dict_data` (`dict_type`, `dict_label`, `dict_value`, `status`) VALUES
('sys_user_status', '正常', '0', '0'),
('sys_user_status', '停用', '1', '0');
-- 脚本执行完成
```
---
## 附录:快速参考
### 文件路径速查
- 设计文档:`docs/design/YYYY-MM-DD-00X-设计名.md`
- SQL 脚本:`docs/sql/YYYY-MM-DD-00X-数据库名.sql`
- 主索引:`docs/index.md`
- 会话记录:`docs/sessions/YYYY-MM-DD-00X-session.md`
- 项目规则:`.trae/rules/project_rules.md`
- SSOT 架构师提示词:`docs/Prompt/0004-单一真源文档驱动架构师.md`
### 工具命令速查
```powershell
# 读取设计文档
Read(file_path="d:\\idea_demo\\datai\\docs\\design\\2026-01-21-001-用户登录功能-设计.md")
# 生成 SQL 脚本
Write(file_path="d:\\idea_demo\\datai\\docs\\sql\\2026-01-21-001-user-login.sql", content="...")
# 读取索引
Read(file_path="d:\\idea_demo\\datai\\docs\\index.md")
# 更新索引
Write(file_path="d:\\idea_demo\\datai\\docs\\index.md", content="...")
# 搜索现有 SQL 脚本
SearchCodebase(information_request="查找 docs/sql 目录下的所有 SQL 脚本")
# 查找所有 SQL 脚本
Glob(pattern="docs/sql/*.sql")
```
### 阶段 4 输出清单
- [ ] SQL 脚本:`docs/sql/YYYY-MM-DD-00X-数据库名.sql`(如果涉及数据库变更)
- [ ] 更新的索引:`docs/index.md`(如果涉及数据库变更)
- [ ] 更新的设计文档:`docs/design/YYYY-MM-DD-00X-设计名.md`(如果涉及数据库变更)
- [ ] 更新的会话记录:`docs/sessions/YYYY-MM-DD-00X-session.md`
### 下一阶段提示
如果用户确认进入下一阶段,请参考:
- [project_rules.md](file:///d:\idea_demo\datai\.trae\rules\project_rules.md) 的"阶段 5提示词生成"
- 准备分析需求的核心任务
- 准备生成针对当前需求的提示词
- 准备更新索引和会话记录