声明模型
GORM 通过将 Go 结构体映射到数据库表来简化数据库交互。理解如何在 GORM 中声明模型是充分利用其全部功能的基础。
声明模型
模型使用普通结构体定义。这些结构体可以包含基本 Go 类型的字段、这些类型的指针或别名,甚至可以是自定义类型,只要它们实现了 database/sql 包中的 Scanner 和 Valuer 接口。
考虑以下 User 模型示例:
type User struct {
ID uint
Name string
Email *string
Age uint8
Birthday *time.Time
MemberNumber sql.NullString
ActivatedAt sql.NullTime
CreatedAt time.Time
UpdatedAt time.Time
ignored string
}在此模型中:
- 直接使用了
uint、string和uint8等基本数据类型。 *string和*time.Time等类型的指针表示可为空的字段。- 来自
database/sql包的sql.NullString和sql.NullTime用于需要更多控制的可为空字段。 CreatedAt和UpdatedAt是特殊字段,GORM 会在记录创建或更新时自动填充当前时间。- 未导出的字段(以小写字母开头的字段)不会被映射。
除了 GORM 模型声明的基本功能之外,重要的是要强调通过 serializer 标签对序列化的支持。此功能增强了从数据库存储和检索数据的灵活性,特别是对于需要自定义序列化逻辑的字段,详见 Serializer 的详细说明。
约定
- 主键:GORM 使用名为
ID的字段作为每个模型的默认主键。 - 表名:默认情况下,GORM 将结构体名称转换为
snake_case并将其变为复数形式作为表名。例如,User结构体在数据库中变为users,GormUserName变为gorm_user_names。 - 列名:GORM 自动将结构体字段名转换为
snake_case作为数据库中的列名。 - 时间戳字段:GORM 使用名为
CreatedAt和UpdatedAt的字段来自动跟踪记录的创建时间和更新时间。
遵循这些约定可以大大减少你需要编写的配置或代码量。然而,GORM 也具有灵活性,允许你在默认约定不满足需求时进行自定义。你可以在 GORM 的 约定 文档中了解更多关于自定义这些约定的信息。
gorm.Model
GORM 提供了一个名为 gorm.Model 的预定义结构体,其中包含常用的字段:
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}- 嵌入到你的结构体中:你可以直接将
gorm.Model嵌入到你的结构体中以自动包含这些字段。这对于在不同模型之间保持一致性以及利用 GORM 的内置约定非常有用,参见 嵌入结构体。 - 包含的字段:
ID:每条记录的唯一标识符(主键)。CreatedAt:记录创建时自动设置为当前时间。UpdatedAt:记录更新时自动更新为当前时间。DeletedAt:用于软删除(将记录标记为已删除,而不会实际将其从数据库中移除)。
高级用法
字段级权限
导出的字段在使用 GORM 进行 CRUD 操作时拥有全部权限,GORM 允许你通过标签更改字段级权限,因此你可以将字段设置为只读、只写、仅创建、仅更新或忽略。
注意 忽略的字段在使用 GORM Migrator 创建表时不会被创建。
type User struct {
Name string `gorm:"<-:create"`
Name string `gorm:"<-:update"`
Name string `gorm:"<-"`
Name string `gorm:"<-:false"`
Name string `gorm:"->"`
Name string `gorm:"->;<-:create"`
Name string `gorm:"->:false;<-:create"`
Name string `gorm:"-"`
Name string `gorm:"-:all"`
Name string `gorm:"-:migration"`
}创建/更新时间/Unix(毫秒/纳秒)秒跟踪
GORM 按照约定使用 CreatedAt 和 UpdatedAt 来跟踪创建/更新时间,如果定义了这些字段,GORM 会在创建/更新时设置 当前时间。
要使用不同名称的字段,你可以通过标签 autoCreateTime、autoUpdateTime 来配置这些字段。
如果你更倾向于保存 UNIX(毫秒/纳秒)秒数而不是时间,你只需将字段的数据类型从 time.Time 更改为 int。
type User struct {
CreatedAt time.Time
UpdatedAt int
Updated int64 `gorm:"autoUpdateTime:nano"`
Updated int64 `gorm:"autoUpdateTime:milli"`
Created int64 `gorm:"autoCreateTime"`
}嵌入结构体
对于匿名字段,GORM 会将其字段包含到其父结构体中,例如:
type Author struct {
Name string
Email string
}
type Blog struct {
Author
ID int
Upvotes int32
}
type Blog struct {
ID int64
Name string
Email string
Upvotes int32
}对于普通结构体字段,你可以使用标签 embedded 来嵌入它,例如:
type Author struct {
Name string
Email string
}
type Blog struct {
ID int
Author Author `gorm:"embedded"`
Upvotes int32
}
type Blog struct {
ID int64
Name string
Email string
Upvotes int32
}你还可以使用标签 embeddedPrefix 为嵌入字段的数据库名称添加前缀,例如:
type Blog struct {
ID int
Author Author `gorm:"embedded;embeddedPrefix:author_"`
Upvotes int32
}
type Blog struct {
ID int64
AuthorName string
AuthorEmail string
Upvotes int32
}字段标签
声明模型时标签是可选的,GORM 支持以下标签:
标签不区分大小写,但推荐使用 camelCase。如果使用多个标签,
它们应该用分号(;)分隔。对解析器具有特殊含义的字符
可以使用反斜杠(\)进行转义,从而可以用作参数值。
| 标签名 | 描述 |
|---|---|
| column | 列的数据库名称 |
| type | 列数据类型,优先使用兼容的通用类型,例如:bool、int、uint、float、string、time、bytes,适用于所有数据库,并可与其他标签一起使用,如 not null、size、autoIncrement……同时支持指定数据库数据类型,如 varbinary(8),使用指定数据库数据类型时,需要是完整的数据库数据类型,例如:MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT |
| serializer | 指定序列化器,用于数据的序列化和反序列化到数据库,例如:serializer:json/gob/unixtime |
| size | 指定列数据大小/长度,例如:size:256 |
| primaryKey | 指定列为主键 |
| unique | 指定列为唯一 |
| default | 指定列默认值 |
| precision | 指定列精度 |
| scale | 指定列小数位数 |
| not null | 指定列为 NOT NULL |
| autoIncrement | 指定列自动递增 |
| autoIncrementIncrement | 自动递增步长,控制连续列值之间的间隔 |
| embedded | 嵌入该字段 |
| embeddedPrefix | 嵌入字段的列名前缀 |
| autoCreateTime | 创建时跟踪当前时间,对于 int 字段,将跟踪 unix 秒,使用值 nano/milli 跟踪 unix 纳秒/毫秒,例如:autoCreateTime:nano |
| autoUpdateTime | 创建/更新时跟踪当前时间,对于 int 字段,将跟踪 unix 秒,使用值 nano/milli 跟踪 unix 纳秒/毫秒,例如:autoUpdateTime:milli |
| index | 创建带选项的索引,多个字段使用相同名称将创建复合索引,详见 索引 |
| uniqueIndex | 与 index 相同,但创建唯一索引 |
| check | 创建检查约束,例如:check:age > 13,详见 约束 |
| <- | 设置字段的写权限,<-:create 仅创建字段,<-:update 仅更新字段,<-:false 无写权限,<- 创建和更新权限 |
| -> | 设置字段的读权限,->:false 无读权限 |
| - | 忽略此字段,- 无读/写权限,-:migration 无迁移权限,-:all 无读/写/迁移权限 |
| comment | 迁移时为字段添加注释 |
关联标签
GORM 允许通过标签为关联配置外键、约束、多对多表,详见 关联部分
评论
登录后参与评论
KnowForge