# 数据库设计规范 本文档定义了 HoTime 框架代码生成器所依赖的数据库设计规范。遵循这些规范可以确保代码生成器正确识别表关系、自动生成 CRUD 接口和管理后台。 --- ## 表命名规则 ### 1. 关于表名前缀 一般情况下**没必要强行添加前缀分组**,直接使用业务含义命名即可: ``` 推荐:user、org、role、article ``` **可以使用前缀的场景**:当项目较大、表较多时,可以用前缀进行模块分组(如 `sys_`、`cms_`),代码生成器会根据 `_` 分词自动将同前缀的表归为一组。 ``` sys_user、sys_role、sys_org → 自动归入 sys 分组 cms_article、cms_category → 自动归入 cms 分组 ``` **使用前缀的注意事项**: - 必须遵循外键全局唯一性规则(见下文) - 前缀分组后,关联 ID 命名会更复杂,容易产生重复 - **外键名不允许重复指向不同的表** ### 2. 可使用简称 较长的表名可以使用常见简称: | 全称 | 简称 | |------|------| | organization | org | | category | ctg | | configuration | config | | administrator | admin | ### 3. 关联表命名 多对多关联表使用 `主表_关联表` 格式: ``` user_org -- 用户与组织的关联 user_role -- 用户与角色的关联 article_tag -- 文章与标签的关联 ``` --- ## 字段命名规则 ### 1. 主键字段 所有表的主键统一命名为 `id`,使用自增整数。 ```sql `id` int(11) NOT NULL AUTO_INCREMENT ``` ### 2. 外键字段 外键使用 `完整表名_id` 格式: ``` user_id -- 指向 user 表 org_id -- 指向 org 表 role_id -- 指向 role 表 app_category_id -- 指向 app_category 表 ``` ### 3. 关联表引用 引用关联表时使用 `关联表名_id`: ``` user_org_id -- 指向 user_org 表 user_role_id -- 指向 user_role 表 ``` ### 4. 外键全局唯一性(重要) **每个 `xxx_id` 字段名必须全局唯一指向一张表**,代码生成器通过 `_id` 后缀自动识别外键关系。 ``` ✅ 正确设计: - user_id 只能指向 user 表 - org_id 只能指向 org 表 - user_org_id 只能指向 user_org 表 - sys_user_id 只能指向 sys_user 表(如果使用前缀分组) ❌ 错误设计: - dd_id 作为"钉钉外部系统ID",但系统中存在 dd 表 → 代码生成器会误判为指向 dd 表的外键 - 同时存在 user 表和 sys_user 表,都使用 user_id → 外键名重复,代码生成器无法正确识别 ``` **使用前缀分组时的外键命名**: 如果使用了表名前缀(如 `sys_user`),外键应使用完整表名: | 表名 | 外键命名 | |------|----------| | sys_user | sys_user_id | | sys_org | sys_org_id | | cms_article | cms_article_id | **非外键业务标识字段**:避免使用 `xxx_id` 格式 | 业务含义 | 错误命名 | 正确命名 | |----------|----------|----------| | 设备唯一标识 | device_id | device_uuid / device_sn | | 钉钉用户ID | dingtalk_user_id | dt_user_id / dingtalk_uid | | 微信OpenID | wechat_id | wechat_openid | | 外部系统编号 | external_id | external_code / external_sn | ### 5. 外键智能匹配机制 代码生成器会按以下优先级自动匹配外键关联的表: 1. **完全匹配**:`user_id` → 查找 `user` 表 2. **带前缀的完全匹配**:如果没找到,尝试 `user_id` → 查找 `sys_user` 表(默认前缀) 3. **去除字段前缀匹配**:如果字段有前缀且找不到对应表,会去掉前缀匹配 **示例**:`admin_user_id` 字段的匹配过程: 1. 先查找 `admin_user` 表 → 如果存在,关联到 `admin_user` 表 2. 如果不存在,去掉前缀查找 `user` 表 → 如果存在,关联到 `user` 表 **使用场景**:当一张表需要记录多个用户(如创建人、审核人、处理人)时: ```sql CREATE TABLE `order` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) COMMENT '下单用户', `audit_user_id` int(11) COMMENT '审核人', `handle_user_id` int(11) COMMENT '处理人', ... ); ``` 如果系统中没有 `audit_user` 和 `handle_user` 表,代码生成器会自动将 `audit_user_id` 和 `handle_user_id` 识别为指向 `user` 表的外键。 ### 6. 关联表冗余外键 关联表应包含必要的冗余外键便于查询: ```sql -- user_app 表(用户与应用的关联) CREATE TABLE user_app ( id int(11) NOT NULL AUTO_INCREMENT, user_id int(11) DEFAULT NULL COMMENT '用户ID', app_id int(11) DEFAULT NULL COMMENT '应用ID', app_category_id int(11) DEFAULT NULL COMMENT '应用分类ID(冗余,便于按分类查询)', ... ); ``` ### 7. 层级关系字段 树形结构的表使用以下字段: | 字段 | 类型 | 说明 | |------|------|------| | parent_id | int | 父级ID,顶级为 NULL 或 0 | | parent_ids | varchar(255) | 完整层级路径,格式:`,1,3,5,`(从根到当前,逗号分隔) | | level | int | 层级深度,从 0 开始 | **示例**: ``` id=1, parent_id=NULL, parent_ids=",1,", level=0 -- 顶级 id=3, parent_id=1, parent_ids=",1,3,", level=1 -- 一级 id=5, parent_id=3, parent_ids=",1,3,5,", level=2 -- 二级 ``` `parent_ids` 的设计便于快速查询所有子级: ```sql SELECT * FROM org WHERE parent_ids LIKE '%,3,%' -- 查询id=3的所有子级 ``` --- ## 时间字段类型 不同数据库使用对应的时间类型: | 数据库 | 类型 | 示例 | |--------|------|------| | MySQL | datetime | `2024-01-15 10:30:00` | | SQLite | TEXT | `2024-01-15 10:30:00` | | PostgreSQL | timestamp | `2024-01-15 10:30:00` | --- ## 表注释规则 ### 表备注命名建议 表备注建议使用"XX管理"格式,便于在管理后台显示: ```sql -- MySQL 表备注示例 CREATE TABLE `user` ( ... ) COMMENT='用户管理'; CREATE TABLE `article` ( ... ) COMMENT='文章管理'; CREATE TABLE `order` ( ... ) COMMENT='订单管理'; ``` ### SQLite 表备注 SQLite 不支持表备注,代码生成器会使用表名作为默认显示名称。如需自定义,可在配置文件中手动设置 `label`(详见代码生成配置规范)。 --- ## 字段注释规则 ### 注释语法格式 字段注释支持以下格式组合: ``` 显示名称:选项值 附加备注{前端提示} ``` | 部分 | 分隔符 | 用途 | |------|--------|------| | 显示名称 | 无 | 前端表单/列表的字段标签 | | 选项值 | `:` 冒号 | select 类型的下拉选项(格式:`值-名称,值-名称`) | | 附加备注 | 空格 | 仅在数据库中查看,不传递给前端 | | 前端提示 | `{}` | 存储到 `ps` 字段,用于前端显示提示文字 | ### 选择类型字段 使用 `标签:值-名称,值-名称` 格式,代码生成器会自动解析为下拉选项: ```sql `state` int(2) DEFAULT '0' COMMENT '状态:0-正常,1-异常,2-隐藏' `sex` int(1) DEFAULT '0' COMMENT '性别:0-未知,1-男,2-女' `status` int(2) DEFAULT '0' COMMENT '审核状态:0-待审核,1-已通过,2-已拒绝' ``` ### 普通字段 直接使用中文说明: ```sql `name` varchar(50) DEFAULT NULL COMMENT '名称' `phone` varchar(20) DEFAULT NULL COMMENT '手机号' `email` varchar(100) DEFAULT NULL COMMENT '邮箱' ``` ### 附加备注(空格后) 空格后的内容**不会传递给前端**,仅供数据库设计时参考: ```sql `user_id` int(11) COMMENT '用户ID 关联user表的主键' `amount` decimal(10,2) COMMENT '金额 单位为元,精确到分' ``` ### 前端提示({}内) `{}` 中的内容存储到 `ps` 字段,前端可用于显示输入提示: ```sql `phone` varchar(20) COMMENT '手机号{请输入11位手机号}' `email` varchar(100) COMMENT '邮箱{格式:xxx@xxx.com}' `content` text COMMENT '内容{支持HTML格式}' ``` ### 组合使用 ```sql -- 完整格式示例 `status` int(2) DEFAULT '0' COMMENT '状态:0-待审核,1-已通过,2-已拒绝 业务状态流转字段{选择当前审核状态}' ``` 解析结果: - `label` = "状态" - `options` = [{name:"待审核", value:"0"}, {name:"已通过", value:"1"}, {name:"已拒绝", value:"2"}] - `ps` = "选择当前审核状态" - 空格后的"业务状态流转字段"不会传递给前端 ### SQLite 字段备注 SQLite 不支持字段备注(COMMENT),代码生成器会使用字段名作为默认显示名称。如需自定义,可在配置文件中手动设置(详见代码生成配置规范)。 --- ## 必有字段规则 每张业务表必须包含以下三个字段: ### MySQL ```sql `state` int(2) DEFAULT '0' COMMENT '状态:0-正常,1-异常,2-隐藏', `create_time` datetime DEFAULT NULL COMMENT '创建日期', `modify_time` datetime DEFAULT NULL COMMENT '变更时间', ``` ### SQLite ```sql "state" INTEGER DEFAULT 0, -- 状态:0-正常,1-异常,2-隐藏 "create_time" TEXT DEFAULT NULL, -- 创建日期 "modify_time" TEXT DEFAULT NULL, -- 变更时间 ``` ### PostgreSQL ```sql "state" INTEGER DEFAULT 0, -- 状态:0-正常,1-异常,2-隐藏 "create_time" TIMESTAMP DEFAULT NULL, -- 创建日期 "modify_time" TIMESTAMP DEFAULT NULL, -- 变更时间 ``` --- ## 完整建表示例 ### MySQL 示例 ```sql -- 用户表 CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `name` varchar(50) DEFAULT NULL COMMENT '用户名', `phone` varchar(20) DEFAULT NULL COMMENT '手机号', `password` varchar(64) DEFAULT NULL COMMENT '密码', `org_id` int(11) DEFAULT NULL COMMENT '组织ID', `role_id` int(11) DEFAULT NULL COMMENT '角色ID', `avatar` varchar(255) DEFAULT NULL COMMENT '头像', `sex` int(1) DEFAULT '0' COMMENT '性别:0-未知,1-男,2-女', `state` int(2) DEFAULT '0' COMMENT '状态:0-正常,1-异常,2-隐藏', `create_time` datetime DEFAULT NULL COMMENT '创建日期', `modify_time` datetime DEFAULT NULL COMMENT '变更时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; -- 组织表(树形结构) CREATE TABLE `org` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `name` varchar(100) DEFAULT NULL COMMENT '组织名称', `parent_id` int(11) DEFAULT NULL COMMENT '父级ID', `parent_ids` varchar(255) DEFAULT NULL COMMENT '层级路径', `level` int(2) DEFAULT '0' COMMENT '层级深度', `sort` int(5) DEFAULT '0' COMMENT '排序', `state` int(2) DEFAULT '0' COMMENT '状态:0-正常,1-异常,2-隐藏', `create_time` datetime DEFAULT NULL COMMENT '创建日期', `modify_time` datetime DEFAULT NULL COMMENT '变更时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='组织表'; -- 用户组织关联表 CREATE TABLE `user_org` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `user_id` int(11) DEFAULT NULL COMMENT '用户ID', `org_id` int(11) DEFAULT NULL COMMENT '组织ID', `state` int(2) DEFAULT '0' COMMENT '状态:0-正常,1-异常,2-隐藏', `create_time` datetime DEFAULT NULL COMMENT '创建日期', `modify_time` datetime DEFAULT NULL COMMENT '变更时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户组织关联表'; ``` ### SQLite 示例 ```sql -- 用户表 CREATE TABLE "user" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT, "name" TEXT DEFAULT NULL, "phone" TEXT DEFAULT NULL, "password" TEXT DEFAULT NULL, "org_id" INTEGER DEFAULT NULL, "role_id" INTEGER DEFAULT NULL, "avatar" TEXT DEFAULT NULL, "sex" INTEGER DEFAULT 0, "state" INTEGER DEFAULT 0, "create_time" TEXT DEFAULT NULL, "modify_time" TEXT DEFAULT NULL ); ``` --- ## 规范检查清单 在设计数据库时,请确认: - [ ] 表名无系统前缀 - [ ] 主键统一为 `id` - [ ] 外键格式为 `表名_id` - [ ] 所有 `xxx_id` 字段都指向实际存在的表 - [ ] 非外键业务标识不使用 `xxx_id` 格式 - [ ] 树形表包含 parent_id、parent_ids、level - [ ] 所有表包含 state、create_time、modify_time - [ ] 选择字段注释格式正确(`标签:值-名称`)