108 lines
5.2 KiB
Markdown
108 lines
5.2 KiB
Markdown
# 3.2 数据库建表
|
||
|
||
:::tip 概述
|
||
建表是模块开发的第一步。本项目对表结构有强约束:统一审计列、int 自增主键、del_flag 软删、uk_* 唯一索引、列注释枚举。这些规范不是建议——它们是全局钩子、字典系统、代码生成器正常工作的前提。
|
||
:::
|
||
|
||
## 统一规范(25 张表齐备)
|
||
|
||
```sql
|
||
-- 审计列(每张表必有)
|
||
id int NOT NULL AUTO_INCREMENT COMMENT '主键ID', -- 数据库自增(禁用雪花)
|
||
create_user varchar(50) DEFAULT '' COMMENT '创建人',
|
||
create_time datetime DEFAULT (now()) COMMENT '创建时间',
|
||
update_user varchar(50) DEFAULT '' COMMENT '更新人',
|
||
update_time datetime DEFAULT (now()) COMMENT '更新时间',
|
||
del_flag int DEFAULT 0 COMMENT '删除标志:0-正常 1-已删除',
|
||
-- 租户级表(9 张)另有:
|
||
tenant_id int DEFAULT 0 COMMENT '租户ID:0-平台级',
|
||
PRIMARY KEY (id)
|
||
```
|
||
|
||
关键决策(与直觉不同的点):
|
||
|
||
::: warning 关键约束
|
||
1. **主键统一 int 数据库自增**(2026-10-13 定稿):禁用雪花算法(`utility/id` 已删除);新增后用 `result.LastInsertId()` 回读;hooks 不填 id。
|
||
2. **删除一律软删**:deleteHook 把物理删除改写为 `UPDATE del_flag=1`,查询由 `dao.Ctx` 恒过滤 `del_flag=0`。
|
||
3. **无物理外键**:全部逻辑外键(如 article.category_id),跨表一致性由业务层保证。
|
||
:::
|
||
|
||
## 唯一索引(uk_*,13 个定稿)
|
||
|
||
唯一索引是并发唯一性的最终保证(`UniqueFields` 预检仅为 UX 层,存在 TOCTOU 竞态)。命名规范 `uk_` 前缀:
|
||
|
||
```sql
|
||
-- 示例:goframe_user 的三个唯一索引(均含 del_flag,软删行不占坑)
|
||
UNIQUE KEY uk_tenant_username (tenant_id, username, del_flag)
|
||
UNIQUE KEY uk_tenant_mobile (tenant_id, mobile, del_flag)
|
||
UNIQUE KEY uk_tenant_code (tenant_id, code, del_flag)
|
||
|
||
-- 全局唯一(平台级表)
|
||
UNIQUE KEY uk_code (code) -- config / dict / param / file_template / tenant
|
||
UNIQUE KEY uk_tenant_name (tenant_id, name, del_flag) -- dept / level / position / category
|
||
```
|
||
|
||
::: tip 索引范围纪律
|
||
含 tenant_id 的唯一索引,模块唯一预检(UniqueFields 的 `Group:"tenant_id"` 或手写检查按行现租户)**范围必须等于索引范围**,否则漏报 1062 或跨租户误报。
|
||
:::
|
||
|
||
## 列注释枚举(字典与生成器的数据源)
|
||
|
||
注释写法 `字段名:1-正常 2-禁用`(`-`、`—`、`=`、`=` 均可作分隔符),生成器解析为前端选项并自动建字典(编码规范 `{模块驼峰}_{字段驼峰}`):
|
||
|
||
```sql
|
||
status int DEFAULT 1 COMMENT '状态:1-正常 2-禁用',
|
||
-- 常见枚举定稿:
|
||
-- article.status 0-正常 1-下架
|
||
-- menu.type 0-菜单 1-权限节点
|
||
-- job.status 0-未发布 1-运行中 2-暂停
|
||
-- job.execute_policy 1-立即执行 2-执行一次 3-放弃执行
|
||
-- job.is_sync 1-同步 0-异步
|
||
-- role.data_scope 1-全部 2-本部门及以下 3-本部门 4-仅本人
|
||
-- login_log.log_type 1-登录 2-退出
|
||
```
|
||
|
||
## 案例演示表(goframe_example)
|
||
|
||
```sql
|
||
CREATE TABLE `goframe_example` (
|
||
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||
`name` varchar(100) NOT NULL DEFAULT '' COMMENT '案例名称',
|
||
`avatar` varchar(255) NOT NULL DEFAULT '' COMMENT '案例图片',
|
||
`type` int NOT NULL DEFAULT 0 COMMENT '案例类型',
|
||
`status` int NOT NULL DEFAULT 1 COMMENT '状态:1-正常 2-禁用',
|
||
`sort` int NOT NULL DEFAULT 0 COMMENT '排序',
|
||
`create_user` varchar(50) NOT NULL DEFAULT '' COMMENT '创建人',
|
||
`create_time` datetime NULL DEFAULT (now()) COMMENT '创建时间',
|
||
`update_user` varchar(50) NOT NULL DEFAULT '' COMMENT '更新人',
|
||
`update_time` datetime NULL DEFAULT (now()) COMMENT '更新时间',
|
||
`del_flag` int NOT NULL DEFAULT 0 COMMENT '删除标志:0-正常 1-已删除',
|
||
PRIMARY KEY (`id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='案例演示表';
|
||
```
|
||
|
||
它演示了最小可用表形态:审计列齐备、status 注释枚举(生成器据此自动创建 `example_status` 字典)、avatar 图片字段(注释含"图片"触发生成器图片识别)。
|
||
|
||
## 建表/变更工作流
|
||
|
||
```text
|
||
1) 以 document/mysql/ 定稿为基准补 ALTER
|
||
(含列注释枚举、uk_* 唯一索引;索引命名 uk_/idx_ 规范)
|
||
2) gf gen dao -c hack/config.yaml 刷新 dao/entity/do(service 手维护)
|
||
3) 同步 document/ 其余四方言脚本(人工校对)
|
||
4) 租户级表 → 修改 internal/model/hooks 的 tenantTables 清单
|
||
(生成器不自动维护此清单!)
|
||
5) go build ./... 重启;必要时 go run ./cmd/migrator 同步到其他环境库
|
||
```
|
||
|
||
## 租户级表判定
|
||
|
||
新增表是否带 `tenant_id` 决定它是否需要加入 `internal/model/hooks/hooks.go` 的 `tenantTables` 清单:
|
||
|
||
| 类型 | 现有表 | 行为 |
|
||
|------|--------|------|
|
||
| 租户级(9 张) | user/role/dept/level/position/article/category/notice/link | 自动过滤 `tenant_id IN(0,自身)`、插入自动盖章 |
|
||
| 平台级 | 其余 16 张 | 无租户过滤(超管可见全量) |
|
||
|
||
漏加清单的后果:租户级表不隔离,所有租户互相可见数据——务必同步。
|