声明模型

GORM 通过将 Go 结构体(Go structs) 映射到数据库表来简化数据库交互。

1 模型定义

模型是使用普通结构体定义的。 这些结构体可以包含具有基本Go类型、指针或这些类型的别名,甚至是自定义类型(只需要实现 database/sql 包中的Scannerarrow-up-rightValuerarrow-up-right接口)。

GORM模型定义参考下面的示例:

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
  ignored      string         // fields that aren't exported are ignored
}

在此模型中:

  • 具体数字类型如 uintstringuint8 直接使用。

  • 指向 *string*time.Time 类型的指针表示可空字段。

  • 来自 database/sql 包的 sql.NullStringsql.NullTime 用于具有更多控制的可空字段。

  • CreatedAtUpdatedAt 是特殊字段,当记录被创建或更新时,GORM 会自动向内填充当前时间。

  • 未导出的字段会被忽略

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

2 约定

2.1 使用ID作为主键

默认情况下,GORM会使用ID作为表的主键

2.2 复数表名

GORM使用结构体的 蛇形命名 并加上复数作为表名。

  • User -〉 users

  • GormUserName -〉gorm_user_names

可以实现 Tabler 接口来更改默认表名

注意: TableName 不支持动态变化,它会被缓存下来以便后续使用。想要使用动态表名,你可以使用 Scopes,例如:

2.3 临时指定表名

可以使用 Table 方法临时指定表名,例如:

2.4 命名策略

GORM 允许用户通过覆盖默认的命名策略来更改默认的命名约定,该策略用于构建表名、列名、连接表名、外键关系名、检查器名、索引名。请查看 配置 以获取详细信息。

2.5 列名

根据约定,数据表的列名使用的是 struct 字段名的 蛇形命名

可以使用 column 标签或 命名策略arrow-up-right 来覆盖列名

2.6 CreatedAt

对于有 CreatedAt 字段的模型,创建记录时,如果该字段值为零值,则将该字段的值设为当前时间

你可以通过将 autoCreateTime 标签置为 false 来禁用时间戳追踪,例如:

2.7 UpdatedAt

对于有 UpdatedAt 字段的模型,更新记录时,将该字段的值设为当前时间。创建记录时,如果该字段值为零值,则将该字段的值设为当前时间

你可以通过将 autoUpdateTime 标签置为 false 来禁用时间戳追踪,例如:

3 grom.Model

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

4 字段级权限控制

可导出的字段在使用 GORM 进行 CRUD 时拥有全部的权限,此外,GORM 允许用标签控制字段级别的权限。这样就可以让一个字段的权限是只读、只写、只创建、只更新或者被忽略

注意: 使用 GORM Migrator 创建表时,不会创建被忽略的字段

5 创建/更新时间追踪

GORM 约定使用 CreatedAtUpdatedAt 追踪创建/更新时间。如果定义了这种字段,GORM 在创建、更新时会自动填充 当前时间

要使用不同名称的字段,可以配置 autoCreateTimeautoUpdateTime 标签。

如果您想要保存 UNIX(毫/纳)秒时间戳,而不是 time,您只需简单地将 time.Time 修改为 int 即可

6 嵌入结构体

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

对于正常的结构体字段,你也可以通过标签 embedded 将其嵌入,例如:

7 字段标签

在声明模型时,标签是可选的,GORM 支持以下标签:标签不区分大小写,但推荐使用驼峰式命名。如果使用多个标签,它们应该由分号(;)分隔。具有特殊意义的字符可以用反斜杠

标签名
说明

column

指定 db 列名

type

列数据类型,推荐使用兼容性好的通用类型,例如:所有数据库都支持 bool、int、uint、float、string、time、bytes 并且可以和其他标签一起使用,例如:not nullsize, 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 字段,它会追踪时间戳秒数,您可以使用 nano/milli 来追踪纳秒、毫秒时间戳,例如:autoCreateTime:nano

autoUpdateTime

创建/更新时追踪当前时间,对于 int 字段,它会追踪时间戳秒数,您可以使用 nano/milli 来追踪纳秒、毫秒时间戳,例如:autoUpdateTime:milli

index

根据参数创建索引,多个字段使用相同的名称则创建复合索引,查看 索引arrow-up-right 获取详情

uniqueIndex

index 相同,但创建的是唯一索引

check

创建检查约束,例如 check:age > 13,查看 约束arrow-up-right 获取详情

<-

设置字段写入的权限, <-:create 只创建、<-:update 只更新、<-:false 无写入权限、<- 创建和更新权限

->

设置字段读的权限,->:false 无读权限

-

忽略该字段,- 表示无读写,-:migration 表示无迁移权限,-:all 表示无读写迁移权限

comment

迁移时为字段添加注释

8 关联标签

GORM 允许通过标签为关联配置外键、约束、many2many 表,详情请参考 关联模式

9 时间处理

如果在字段中想使用 time.Time 必须注意几个问题:

  1. 查询中数据库中返回的是string, 解决方法为在DNS中添加 ?parseTime=true 连接参数

  2. 当前事情时间存入的时候ORM处理为UTC时间

    1. 使用的时候需要保证大家对时区的理解是一致的,多数采用UTC

    2. 保证写入时间和读取时间理解一致

  3. 使用时间戳 -》UTC时间 -〉Local() 推荐

最后更新于