5分钟跑通 HotGo 数据库:GoFrame ORM 连接配置与 CRUD 代码生成
【免费下载链接】hotgoHotGo 是AI 赋能企业级全栈前后端分离开发及移动应用基础平台,基于 Vue 和 GoFrame2.0 构建;内置 AI 开发规范、适配主流 AI 开发工具,人机协同高效开发。集成 jwt 鉴权、动态路由菜单、casbin 鉴权、消息队列、定时任务等功能,预置各类常用场景文件,助力专注业务开发。项目地址: https://gitcode.com/GitHub_Trending/ho/hotgo
做一个中后台系统,最耗时间的往往不是业务逻辑,而是数据库这条链:每张表手工铺一遍 DAO、控制器、表单、列表页,一天就耗在接线上了。HotGo 把这条链路压成了一步——只要建表时遵守字段约定,后台的「代码生成」就能产出 API、控制器、业务逻辑甚至 Vue 页面文件,热编译下生成完直接可用。这篇文章带你走一遍 HotGo 数据库层的完整玩法:从连接配置、表结构约定,到生成后的增删改查,再到事务、关联查询和分页优化的少踩坑写法。
快速上手 ⚡
先说目标:5 分钟内,让浏览器打开一个能登录、能查业务数据的后台。假设你本机已装好 Go(≥1.23)、Node(≥20)和 MySQL(≥5.7,InnoDB 引擎,或 PostgreSQL ≥14),并建好了hotgo库(库怎么建、配置怎么填,下一节细讲),现在只需要把服务拉起来。
克隆仓库并启动服务端,监听 8000 端口:
git clone https://gitcode.com/GitHub_Trending/ho/hotgo cd hotgo/server go mod tidy go run main.go再开一个终端启动前端:
cd hotgo/web pnpm install pnpm run dev # 默认 8001 端口浏览器打开http://localhost:8001/admin,用admin / 123456登录,看到的就是下图这个管理后台。
登录页底部那排演示角色按钮点一下就能进后台——主面板的卡片指标、流量趋势都在实时读业务表,说明 HotGo 数据库链路已经全程通了。跑通这一步后,我们看看它内部怎么分工。
看懂架构:一次请求穿过哪四层
一条 CRUD 请求在 HotGo 里经过的分工是这样的:
Vue 页面 (web/src/views) │ HTTP + JSON ▼ router / controller 参数绑定、登录与权限拦截 ▼ logic 业务逻辑:校验、事务、数据组装 ▼ dao 每张表一个 Go 文件:列名、主键、Transaction ▼ gdb (GoFrame ORM) ──► MySQL / PostgreSQLserver/internal/dao/:每张数据表对应一个文件,由 GoFrame CLI 生成,提供表全局实例和列名常量server/internal/logic/:业务代码住在这里,列表、新增、修改、删除都是它server/internal/library/hgorm/:HotGo 自研数据库库,提供关联表 Join、关键词多条件查询、软删除/租户/操作人钩子server/manifest/config/config.yaml:唯一决定「连哪个库」的地方hggen:后台「开发工具 → 代码生成」背后的引擎,把表结构变成整套 CRUD
数据流向永远是单向的:页面 → 控制器 → 逻辑层 → dao → gdb。你写业务只碰 logic 和 dao 两层,其余框架代劳。
逐步配置:三步完成安装
1. 建库并导入初始表结构
仓库里带了完整建库脚本,导入它你就拥有了菜单、角色、字典等全套基础表:
mysql -uroot -p -e "CREATE DATABASE hotgo DEFAULT CHARSET utf8mb4;" mysql -uroot -p hotgo < hotgo/storage/data/hotgo.sql执行完SHOW TABLES;能看到hg_admin_member、hg_sys_config等以hg_为前缀的表,建库成功。
2. 配置数据库连接
复制配置模板并修改连接串,这一步决定后端连哪个库:
cd hotgo/server/manifest/config cp config.example.yaml config.yaml编辑config.yaml里的database.default.link:
database: default: # 格式:mysql:账号:密码@tcp(主机:端口)/库名?参数 link: "mysql:hotgo:hg123456.@tcp(127.0.0.1:3306)/hotgo?loc=Local&parseTime=true&charset=utf8mb4" Prefix: "hg_" # 表前缀,dao 生成时会自动剥掉注意 DSN 末尾的parseTime=true不能省,否则 datetime 字段无法映射为 Go 时间类型;Prefix要和建库脚本的前缀一致。想用 PostgreSQL 就把 link 换成"pgsql:postgres:hg123456@tcp(127.0.0.1:5432)/hotgo",完整示例见 config.example.yaml。
还有一处容易漏:server/hack/config.yaml里也有一份数据库配置,它供代码生成器读取表结构,两份必须保持一致,否则会报权限错误(排错手册里有对应条目)。
3. 启动并验证
按「快速上手」里的命令分别启动server和web,登录后台。看到主面板出数,配置就全部生效了;若连接报错,九成是 link 写错或库没建。
核心用法:给「测试分类」做一套增删改查
HotGo 有个内置演示表hg_test_category(测试分类),我们直接以它为例走一遍业务线。先说清表结构约定,这是代码生成的门票:
id:bigint 主键,必须有created_at/updated_at:自动填充创建/修改时间deleted_at:存在即启用软删除,查询自动过滤,删除只更新时间不删数据status、sort:状态与排序,表单会默认生成下拉和递增排序值- 字段注释会直接变成页面列名
完整规则见 数据库字段约定文档。登录后台 → 开发工具 → 代码生成,选中hg_test_category,在字段设置页勾选要展示、可查询的列后提交生成(流程截图见 生成 CURD 指南)。生成完,后台菜单自动多出一个「测试分类」,列表页长这样:
菜单、路由、API、页面全部就位。下面看生成出来的后端代码,重点在 logic 层。
列表:拼条件 + 分页。这段代码解决「按名称搜索、分页返回」的问题:
mod := s.Model(ctx) // 自动带上 deleted_at IS NULL 软删除过滤 mod = mod.Fields(sysin.TestCategoryListModel{}) // 只取列表需要的列 if in.Name != "" { mod = mod.WhereLike(dao.TestCategory.Columns().Name, "%"+in.Name+"%") } mod = mod.Page(in.Page, in.PerPage) // 分页 mod = mod.OrderAsc(dao.TestCategory.Columns().Sort).OrderDesc(dao.TestCategory.Columns().Id) err = mod.ScanAndCount(&list, &totalCount, false) // 数据与总数一次拿跑完你能看到后台的分类列表支持名称模糊搜索、按 sort 升序 + id 降序排列,分页器总数准确。s.Model(ctx)是生成代码的统一入口,软删除过滤就在这里自动生效,你不用手写。
新增/修改:一个方法包办,套上事务。有 ID 走更新、无 ID 走插入,保证写操作原子性:
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { if in.Id > 0 { // 有主键:更新 return s.Model(ctx).Fields(sysin.TestCategoryUpdateFields{}). WherePri(in.Id).Data(in).Update() } // 无主键:插入,空字段自动忽略 return s.Model(ctx, &handler.Option{FilterAuth: false}). Fields(sysin.TestCategoryInsertFields{}).Data(in).OmitEmptyData().Insert() })执行后列表里出现新分类行,created_at、created_by由框架钩子自动填充——操作人来自当前登录上下文,你一行都不用写。
删除:软删除。生成的删除逻辑只有一句:
// Unscoped 跳过软删除过滤,定位到目标行 // 框架只更新 deleted_at,不物理删除数据 s.Model(ctx).WherePri(in.Id).Unscoped().Delete()跑完该行立即从列表消失,数据库里它还在,deleted_at有了值。后悔了直接把这个字段置空就能"恢复"。
进阶技巧:事务、关联查询与分页
多表写入必须套事务。以提现申请为例:要同时写提现记录和扣减余额,任何一步失败都得整体回滚:
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { id, err := dao.AdminCash.Ctx(ctx).Data(g.Map{ dao.AdminCash.Columns().MemberId: in.MemberId, dao.AdminCash.Columns().Money: in.Money, // ...其他字段 }).InsertAndGetId() // 1. 写提现记录 if err != nil { return err } // 2. 扣余额;此处失败则上面那条记录一起回滚 _, err = service.AdminCreditsLog().SaveBalance(ctx, /* ... */) return err })跑完的效果是:余额扣成功才存在提现记录,扣失败两边都不留痕。完整写法见 cash.go。
关联表字段一次 JOIN 出来。列表要展示"分类名称"这类关联表字段时,别循环查 N 次主表——HotGo 在 hgorm 库 提供了 Join 工具,主表和关联表字段在一条 SQL 里取齐:
// 生成 `hg_test_category`.`id` = `hg_sys_gen_curd_demo`.`category_id` cond := hgorm.GenJoinOnRelation("hg_sys_gen_curd_demo", "category_id", "hg_test_category", "testCategory", "id") mod = mod.LeftJoin(cond...). Where(dao.SysGenCurdDemo.Columns().Status, 1)执行后每行数据直接带上别名为testCategory的分类字段,没有 N+1 问题。多表关联的完整生成流程参考 关联表 CURD 指南。
分页与查询性能三件事。一是先Count()为 0 就提前返回,省掉空页查询;二是Fields限定返回列,别把 text 大字段全量拖出;三是关键词搜索用hgorm.FilterKeywordsWithOr对多列做 OR 匹配,代替手写一长串 Where。按约定,字符串字段默认 LIKE、数字与时间默认精确匹配,查询习惯和 SQL 默认查询方式 对齐即可。生成的分页列表就是这样的效果:
排错手册:四个高频问题
| 现象 | 原因 | 解法 |
|---|---|---|
代码生成报fetching tables failed ... Access denied 1045 | config.yaml与hack/config.yaml两份数据库配置不一致,或账号无该库权限 | 保持 server/manifest/config/config.yaml 与 server/hack/config.yaml 的 link 一致,用该账号手动SHOW TABLES验证权限 |
| 刚生成完,页面提示"服务器错误,请稍候重试"或 404 | 热编译触发了服务端重启,前端先加载完、接口后恢复 | 等几秒刷新;不放心就手动重启 server |
| 后台看不到「开发工具」菜单 | system.mode设为product时开发功能自动隐藏 | 把config.yaml里mode改回develop |
| datetime 字段报时间解析/映射错误 | DSN 缺parseTime=true | 在 link 参数里补上parseTime=true&loc=Local&charset=utf8mb4 |
更细的生成类问题可翻 生成常见问题。
收束
HotGo 数据库的思路可以浓缩成两句话:用表结构约定换代码生成,用 dao 与 logic 分层换可维护性。把本文的链路走通后,建议按三个方向继续:读一遍 storage/data/hotgo.sql,建表语句就是字段约定的最佳字典;改一改config.yaml里hggen的模板路径,让生成的代码长成你要的样子;跑一跑 casbin_test.go、sorter_test.go 这类仓库自带测试用例,看框架能力的边界。整套中文文档在 docs/guide-zh-CN/ 目录下,遇到问题先从那里找。
【免费下载链接】hotgoHotGo 是AI 赋能企业级全栈前后端分离开发及移动应用基础平台,基于 Vue 和 GoFrame2.0 构建;内置 AI 开发规范、适配主流 AI 开发工具,人机协同高效开发。集成 jwt 鉴权、动态路由菜单、casbin 鉴权、消息队列、定时任务等功能,预置各类常用场景文件,助力专注业务开发。项目地址: https://gitcode.com/GitHub_Trending/ho/hotgo
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考