使用 ID 作为主键

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

  1. type User struct {
  2.   ID   string // 默认情况下,名为 `ID` 的字段会作为表的主键
  3.   Name string
  4. }

你可以通过标签 primaryKey 将其它字段设为主键

  1. // 将 `UUID` 设为主键
  2. type Animal struct {
  3.   ID     int64
  4.   UUID   string `gorm:"primaryKey"`
  5.   Name   string
  6.   Age    int64
  7. }

此外,您还可以看看 复合主键

复数表名

GORM 使用结构体名的 蛇形命名 作为表名。对于结构体 User,根据约定,其表名为 users

TableName

您可以实现 Tabler 接口来更改默认表名,例如:

  1. type Tabler interface {
  2. TableName() string
  3. }
  4. // TableName 会将 User 的表名重写为 `profiles`
  5. func (User) TableName() string {
  6.   return "profiles"
  7. }

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

  1. func UserTable(user User) func (tx *gorm.DB) *gorm.DB {
  2. return func (tx *gorm.DB) *gorm.DB {
  3. if user.Admin {
  4. return tx.Table("admin_users")
  5. }
  6. return tx.Table("users")
  7. }
  8. }
  9. db.Scopes(UserTable(user)).Create(&user)

临时指定表名

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

  1. // 根据 User 的字段创建 `deleted_users` 表
  2. db.Table("deleted_users").AutoMigrate(&User{})
  3. // 从另一张表查询数据
  4. var deletedUsers []User
  5. db.Table("deleted_users").Find(&deletedUsers)
  6. // SELECT * FROM deleted_users;
  7. db.Table("deleted_users").Where("name = ?", "jinzhu").Delete(&User{})
  8. // DELETE FROM deleted_users WHERE name = 'jinzhu';

查看 from 子查询 了解如何在 FROM 子句中使用子查询

命名策略

GORM allows users to change the default naming conventions by overriding the default NamingStrategy, which is used to build TableName, ColumnName, JoinTableName, RelationshipFKName, CheckerName, IndexName, Check out GORM Config for details

列名

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

  1. type User struct {
  2.   ID        uint      // 列名是 `id`
  3.   Name      string    // 列名是 `name`
  4.   Birthday  time.Time // 列名是 `birthday`
  5.   CreatedAt time.Time // 列名是 `created_at`
  6. }

您可以使用 column 标签或 命名策略 来覆盖列名

  1. type Animal struct {
  2.   AnimalID int64     `gorm:"column:beast_id"`         // 将列名设为 `beast_id`
  3.   Birthday time.Time `gorm:"column:day_of_the_beast"` // 将列名设为 `day_of_the_beast`
  4.   Age      int64     `gorm:"column:age_of_the_beast"` // 将列名设为 `age_of_the_beast`
  5. }

时间戳追踪

CreatedAt

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

  1. db.Create(&user) // 将 `CreatedAt` 设为当前时间
  2. user2 := User{Name: "jinzhu", CreatedAt: time.Now()}
  3. db.Create(&user2) // user2 的 `CreatedAt` 不会被修改
  4. // 想要修改该值,您可以使用 `Update`
  5. db.Model(&user).Update("CreatedAt", time.Now())

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

  1. type User struct {
  2. CreatedAt time.Time `gorm:"autoCreateTime:false"`
  3. }

UpdatedAt

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

  1. db.Save(&user) // 将 `UpdatedAt` 设为当前时间
  2. db.Model(&user).Update("name", "jinzhu") // 会将 `UpdatedAt` 设为当前时间
  3. db.Model(&user).UpdateColumn("name", "jinzhu") // `UpdatedAt` 不会被修改
  4. user2 := User{Name: "jinzhu", UpdatedAt: time.Now()}
  5. db.Create(&user2) // 创建记录时,user2 的 `UpdatedAt` 不会被修改
  6. user3 := User{Name: "jinzhu", UpdatedAt: time.Now()}
  7. db.Save(&user3) // 更新时,user3 的 `UpdatedAt` 会修改为当前时间

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

  1. type User struct {
  2. UpdatedAt time.Time `gorm:"autoUpdateTime:false"`
  3. }

注意 GORM 支持拥有多种类型的时间追踪字段。可以根据 UNIX(毫/纳)秒,查看 Model 获取详情