gin-vue-admin Model 层开发指南:GORM 实体定义、标签规范与字段类型约定
【免费下载链接】gin-vue-admin🚀Vite+Vue3+Gin的开发基础平台,支持TS和JS混用。它集成了JWT鉴权、权限管理、动态路由、显隐可控组件、分页封装、多点登录拦截、资源权限、上传下载、代码生成器【可AI辅助】、表单生成器和可配置的导入导出等开发必备功能。项目地址: https://gitcode.com/flipped-aurora/gin-vue-admin
导读
本文面向在 gin-vue-admin 项目中新增或修改数据库实体的开发者(包括 AI 辅助编码场景),系统讲解后端server/model/**目录下数据模型(Model)的编写规范。你将掌握global.GVA_MODEL基类的继承方式、json与gorm双标签的使用约定、关联关系的声明方法、字段命名与类型一致性要点,并结合仓库中的真实模型文件(如sys_api_token.go、sys_user.go)获得可直接照抄的实战写法。
背景:Model 在分层架构中的定位
gin-vue-admin 后端采用经典的分层结构:router → api → service → model,其中Model 负责定义数据库实体与持久化字段,是 Service 与数据库交互的基础。项目目录划分见 server/model,主要包含三块:
server/model/system:系统核心实体(用户、角色、菜单、API、字典、操作记录等);server/model/example:示例业务实体(客户、文件上传下载等),也是代码生成器的参考样板;server/model/common:公共基类型,如JSONMap、JSONSlice等自定义字段类型。
当你需要新增一张业务表、为现有表补字段、或定义 GORM 结构与关联关系时,就应当遵循本文介绍的写法。这也是 aiDoc/examples/backend 中约定的后端分层示例之一(其余还有 request、service、api、router、enter.go 等示例,见 model-example.md)。
一、什么时候应该写 Model 文件
根据 model-example.md 的约定,以下场景需要在server/model/**中新增或修改代码:
- 新增一张业务表:定义全新的持久化实体,对应数据库中的一张新表;
- 为现有表补字段:在已有实体上扩展持久化字段;
- 需要定义 GORM 结构与关联关系:声明一对一、一对多、多对多关系,或需要定制表名、索引、默认值等。
注意:仅用于请求参数校验、或仅用于接口展示(如列表视图 DTO)的数据,不应直接塞进数据库 model,而是放在对应的request/response包中(如 server/model/system/request 与 server/model/system/response)。
二、推荐写法示例
model-example.md 给出了一个最小可用的订单模型示例:
package system import "github.com/flipped-aurora/gin-vue-admin/server/global" type Order struct { global.GVA_MODEL Name string `json:"name" gorm:"comment:订单名称"` Status int `json:"status" gorm:"default:1;comment:订单状态"` Remark string `json:"remark" gorm:"comment:备注"` CreatorID uint `json:"creatorId" gorm:"comment:创建人ID"` }几个关键点:
- 结构体命名为
Order,对应表名默认是复数蛇形形式orders; - 首行嵌入
global.GVA_MODEL,自动获得主键与时间字段; - 每个业务字段必须同时带
json标签(接口输出用)与gorm标签(字段约束用); - 布尔、枚举类字段建议声明默认值,如
default:1。
三、为什么这样写:标签背后的原理
3.1 继承global.GVA_MODEL基类
global.GVA_MODEL定义在 server/global/model.go:
type GVA_MODEL struct { ID uint `gorm:"primarykey" json:"ID"` // 主键ID CreatedAt time.Time // 创建时间 UpdatedAt time.Time // 更新时间 DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` // 删除时间 }继承它带来的效果:
- 主键风格统一:
ID为uint自增主键,所有表主键命名一致; - 时间字段统一:自动获得
CreatedAt、UpdatedAt,GORM 会自动维护; - 软删除开箱即用:
DeletedAt gorm.DeletedAt实现了 GORM 软删除——删除操作变为逻辑删除(写入删除时间),查询时自动过滤已删除记录,且该字段通过json:"-"隐藏,不会出现在接口输出中。
从源码结构看,几乎所有业务实体(sys_api_token.go、exa_customer.go 等)都以嵌入global.GVA_MODEL开头,这是项目内最强的一致性原则。
3.2json标签:前后端字段契约
json标签决定结构体序列化为 JSON 时的字段名,是前端接口契约。例如sys_api_token.go中:
UserID uint `json:"userId" gorm:"comment:用户ID"` AuthorityID uint `json:"authorityId" gorm:"comment:角色ID"`前端拿到的字段就是userId、authorityId(驼峰命名),而 Go 源码中则是UserID、AuthorityID(大驼峰)。两者通过标签解耦,因此:
- 字段命名要清晰、稳定,避免随意改名造成前端联动修改;
- 同一字段在前后端必须使用相同语义的命名(如
userId就统一用userId),这正是 model-example.md 强调的"字段命名尽量清晰、稳定,便于前后端保持一致"。
3.3gorm标签:字段级数据库约束
gorm标签用于约束字段类型、默认值和注释。常见用法汇总(均来自仓库真实代码):
| 用法 | 示例 | 含义 |
|---|---|---|
| 字段注释 | gorm:"comment:订单名称" | 生成表结构时写入字段注释 |
| 默认值 | gorm:"default:1;comment:订单状态" | 插入时未指定则取默认值 |
| 类型指定 | gorm:"type:text;comment:Token" | 强制指定数据库列类型(长文本等) |
| 索引 | gorm:"index;comment:用户UUID" | 为该字段建普通索引 |
| 唯一 | gorm:"not null;unique;primary_key" | 非空 + 唯一(如角色 ID,见 sys_authority.go) |
| 外键 | gorm:"foreignKey:UserID" | 声明关联外键 |
| 多对多 | gorm:"many2many:sys_user_authority;" | 声明连接表 |
| 内嵌结构 | gorm:"embedded" | 将子结构字段扁平化嵌入本表 |
| 忽略字段 | gorm:"-" | 不映射数据库列(仅用于内存计算/展示) |
参考实例:sys_user.go中HeaderImg带default:https://...(头像默认值)、AuthorityId带default:888;sys_operation_record.go中Agent、Body、Resp使用type:text存放可能较长的内容。
四、进阶:关联关系与自定义字段
4.1 外键关联(belongs to / has many)
server/model/system/sys_api_token.go 展示了外键关联的标准写法:
type SysApiToken struct { global.GVA_MODEL UserID uint `json:"userId" gorm:"comment:用户ID"` User SysUser `json:"user" gorm:"foreignKey:UserID;"` AuthorityID uint `json:"authorityId" gorm:"comment:角色ID"` Token string `json:"token" gorm:"type:text;comment:Token"` Status bool `json:"status" gorm:"default:true;comment:状态"` // true有效 false无效 ExpiresAt time.Time `json:"expiresAt" gorm:"comment:过期时间"` Remark string `json:"remark" gorm:"comment:备注"` }要点:
- 同时保留外键字段
UserID和关联字段User SysUser,通过gorm:"foreignKey:UserID"绑定; SysUser类型来自同包定义(sys_user.go),跨包引用时需显式 import(见 exa_customer.go 中对system.SysUser的引用);- 关联字段也带
json标签,方便接口输出嵌套用户信息。
4.2 多对多与自关联
server/model/system/sys_user.go 演示了多对多(用户 ↔ 角色):
Authorities []SysAuthority `json:"authorities" gorm:"many2many:sys_user_authority;"`连接表sys_user_authority由 GORM 自动维护,无需手动建实体。
server/model/system/sys_dictionary.go 演示了一对多自关联(父字典 → 子字典):
ParentID *uint `json:"parentID" gorm:"column:parent_id;comment:父级字典ID"` Children []SysDictionary `json:"children" gorm:"foreignKey:ParentID"`注意父字段用*uint(允许为空表示顶级节点),并用column:parent_id显式指定列名以保持蛇形命名。同样的自关联模式也出现在 sys_dictionary_detail.go。
4.3 自定义表名
默认表名由 GORM 根据结构体名推导(复数蛇形)。需要定制时实现TableName()方法,例如 sys_user.go:
func (SysUser) TableName() string { return "sys_users" }server/model/system/sys_api.go 同样通过该方法将SysApi映射到sys_apis。这是保持系统内表名命名统一(复数、蛇形)的可靠手段。
4.4 JSON 类型字段(公共基类型)
gin-vue-admin 在 server/model/common/basetypes.go 中提供了可直接使用的 JSON 字段类型:
JSONMap:map[string]any,序列化为 JSON 列;JSONSlice[T]:泛型切片,如[]string、[]int。
它们实现了driver.Valuer/sql.Scanner,并会根据方言自动选择数据库列类型:MySQL 为JSON(旧版/ MariaDB 回退LONGTEXT)、PostgreSQL 为JSONB。使用示例见 sys_user.go 中的OriginSetting common.JSONMap字段,搭配gorm:"type:text;default:null;column:origin_setting;comment:配置;"使用。
五、常见错误清单(务必规避)
model-example.md 明确列出了以下高频问题:
- 缺少
json或gorm标签:字段将无法正确输出到接口或无法生成合理的表结构; - 把仅用于请求或展示的字段直接写入数据库 model:应放入
request/response包,避免污染表结构(如按钮权限等只读计算字段在sys_dictionary_detail.go中用gorm:"-"排除); - 同一个字段在前后端使用不同类型:前端
userId为字符串、后端却定义为uint,会导致类型不匹配与隐性 bug; - 忽略
Status、ID、时间字段这类高风险类型一致性问题:ID统一用uint、状态字段统一用int/bool、时间统一用time.Time,并尽量使用global.GVA_MODEL继承的字段,避免重复定义主键与时间字段造成风格分裂。
六、真实参考文件
以下是仓库中可直接参考的成熟 Model 文件,建议在动手前逐一对照:
- server/model/system/sys_api_token.go:外键关联 +
type:text长文本 + 默认值 + 时间字段的完整示例; - server/model/system/sys_user.go:多对多、索引、默认值、
TableName()、common.JSONMap综合示例; - server/model/system/sys_base_menu.go:
gorm:"embedded"内嵌子结构、多对多、gorm:"-"忽略字段示例; - server/model/system/sys_authority.go:自定义主键(
primary_key)与not null;unique约束示例; - server/model/system/sys_operation_record.go:
time.Duration、type:text、关联用户字段示例; - server/model/example/exa_customer.go:跨包引用
system.SysUser的示例业务实体。
结语
Model 层是 gin-vue-admin 后端数据链路的基石。遵循本文约定——统一继承global.GVA_MODEL、为每个持久化字段同时声明json与gorm标签、按需声明关联关系与自定义表名、保持字段命名与类型的前后端一致——就能让新增的业务表与既有系统风格完全对齐,也能让 AI 辅助生成的后端代码与人工代码无缝衔接,减少后续维护成本。
【免费下载链接】gin-vue-admin🚀Vite+Vue3+Gin的开发基础平台,支持TS和JS混用。它集成了JWT鉴权、权限管理、动态路由、显隐可控组件、分页封装、多点登录拦截、资源权限、上传下载、代码生成器【可AI辅助】、表单生成器和可配置的导入导出等开发必备功能。项目地址: https://gitcode.com/flipped-aurora/gin-vue-admin
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考