声明模型

GORM 通过将 Go 结构体映射到数据库表来简化数据库交互。了解如何在 GORM 中声明模型是利用其全部功能的基础。

声明模型

模型使用普通的结构体定义。这些结构体可以包含具有基本 Go 类型、指针或这些类型的别名,甚至是自定义类型的字段,只要它们实现了 database/sql 包中的 ScannerValuer 接口

考虑以下 User 模型的示例

type User struct {
ID uint // Standard field for the primary key
Name string // A regular string field
Email *string // A pointer to a string, allowing for null values
Age uint8 // An unsigned 8-bit integer
Birthday *time.Time // A pointer to time.Time, can be null
MemberNumber sql.NullString // Uses sql.NullString to handle nullable strings
ActivatedAt sql.NullTime // Uses sql.NullTime for nullable time fields
CreatedAt time.Time // Automatically managed by GORM for creation time
UpdatedAt time.Time // Automatically managed by GORM for update time
}

在这个模型中

  • 基本数据类型,如 uintstringuint8,直接使用。
  • 指向类型的指针,如 *string*time.Time,表示可为空的字段。
  • database/sql 包中的 sql.NullStringsql.NullTime 用于需要更多控制的可为空字段。
  • CreatedAtUpdatedAt 是特殊字段,GORM 会在创建或更新记录时自动使用当前时间填充它们。

除了 GORM 中模型声明的基本功能外,重要的是要强调通过序列化器标签对序列化的支持。此功能增强了从数据库存储和检索数据的灵活性,特别是对于需要自定义序列化逻辑的字段,有关详细说明,请参阅 序列化器

约定

  1. 主键:GORM 使用名为 ID 的字段作为每个模型的默认主键。

  2. 表名:默认情况下,GORM 会将结构体名称转换为 snake_case 并将其复数形式用于表名。例如,User 结构体在数据库中变为 users

  3. 列名:GORM 会自动将结构体字段名称转换为 snake_case,以用于数据库中的列名。

  4. 时间戳字段:GORM 使用名为 CreatedAtUpdatedAt 的字段来自动跟踪记录的创建时间和更新时间。

遵循这些约定可以大大减少您需要编写的配置或代码量。但是,GORM 也很灵活,允许您在默认约定不符合您的要求时自定义这些设置。您可以在 GORM 关于 约定 的文档中了解更多有关自定义这些约定的信息。

gorm.Model

GORM 提供了一个名为 gorm.Model 的预定义结构体,其中包含常用的字段

// gorm.Model definition
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"` // allow read and create
Name string `gorm:"<-:update"` // allow read and update
Name string `gorm:"<-"` // allow read and write (create and update)
Name string `gorm:"<-:false"` // allow read, disable write permission
Name string `gorm:"->"` // readonly (disable write permission unless it configured)
Name string `gorm:"->;<-:create"` // allow read and create
Name string `gorm:"->:false;<-:create"` // createonly (disabled read from db)
Name string `gorm:"-"` // ignore this field when write and read with struct
Name string `gorm:"-:all"` // ignore this field when write, read and migrate with struct
Name string `gorm:"-:migration"` // ignore this field when migrate with struct
}

创建/更新时间/Unix(毫秒/纳秒)秒跟踪

GORM 按照惯例使用 CreatedAtUpdatedAt 来跟踪创建/更新时间,如果定义了这些字段,GORM 将在创建/更新时设置 当前时间

要使用具有不同名称的字段,可以使用标签 autoCreateTimeautoUpdateTime 配置这些字段

如果您希望保存 UNIX(毫秒/纳秒)秒而不是时间,则只需将字段的数据类型从 time.Time 更改为 int 即可

type User struct {
CreatedAt time.Time // Set to current time if it is zero on creating
UpdatedAt int // Set to current unix seconds on updating or if it is zero on creating
Updated int64 `gorm:"autoUpdateTime:nano"` // Use unix nano seconds as updating time
Updated int64 `gorm:"autoUpdateTime:milli"`// Use unix milli seconds as updating time
Created int64 `gorm:"autoCreateTime"` // Use unix seconds as creating time
}

嵌入结构体

对于匿名字段,GORM 会将其字段包含在其父结构体中,例如

type User struct {
gorm.Model
Name string
}
// equals
type User struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
Name string
}

对于普通的结构体字段,可以使用标签 embedded 来嵌入它,例如

type Author struct {
Name string
Email string
}

type Blog struct {
ID int
Author Author `gorm:"embedded"`
Upvotes int32
}
// equals
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
}
// equals
type Blog struct {
ID int64
AuthorName string
AuthorEmail string
Upvotes int32
}

字段标签

在声明模型时,标签是可选的,GORM 支持以下标签
标签不区分大小写,但建议使用 camelCase 形式。

标签名称 描述
column 数据库列名
type 列数据类型,建议使用兼容的通用类型,例如:bool、int、uint、float、string、time、bytes,这些类型适用于所有数据库,并且可以与其他标签一起使用,例如 not nullsizeautoIncrement... 也支持指定数据库数据类型,例如 varbinary(8),当使用指定的数据库数据类型时,它需要是一个完整的数据库数据类型,例如:MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT
serializer 指定如何将数据序列化和反序列化到数据库的序列化器,例如:serializer:json/gob/unixtime
size 指定列数据大小/长度,例如:size:256
primaryKey 指定列为主键
unique 指定列为唯一
default 指定列默认值
precision 指定列精度
scale 指定列小数位数
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 允许通过关联的标签配置外键、约束、多对多表,有关详细信息,请查看关联部分

铂金赞助商

黄金赞助商

铂金赞助商

黄金赞助商