gorm声明模型

本文详细介绍了如何使用GORM在Go语言中声明模型,包括标准struct的定义、约定、gorm.Model的使用、字段级权限控制、时间追踪和嵌入结构体。同时涵盖了标签配置的各个方面,以实现高效的数据管理和权限管理。

gorm声明模型

本文视频教程:https://www.bilibili.com/video/BV1zR4y1t7Wj?from=search&seid=7543476481899300801&spm_id_from=333.337.0.0

模型定义

模型是标准的 struct,由 Go 的基本数据类型、实现了 ScannerValuer 接口的自定义类型及其指针或别名组成

例如:

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
}

约定

GORM 倾向于约定,而不是配置。默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAtUpdatedAt 字段追踪创建、更新时间

遵循 GORM 已有的约定,可以减少您的配置和代码量。如果约定不符合您的需求,GORM 允许您自定义配置它们

gorm.Model

GORM 定义一个 gorm.Model 结构体,其包括字段 IDCreatedAtUpdatedAtDeletedAt

// gorm.Model 的定义
type Model struct {
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
}

您可以将它嵌入到您的结构体中,以包含这几个字段,详情请参考 嵌入结构体

高级选项

字段级权限控制

可导出的字段在使用 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"` // 仅创建(禁止从 db 读)
  Name string `gorm:"-"`  // 通过 struct 读写会忽略该字段
}

创建/更新时间追踪(纳秒、毫秒、秒、Time)

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

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

如果您想要保存 UNIX(毫/纳)秒时间戳,而不是 time,您只需简单地将 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
}
// 等效于
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
}
// 等效于
type Blog struct {
  ID    int64
  Name  string
  Email string
  Upvotes  int32
}

并且,您可以使用标签 embeddedPrefix 来为 db 中的字段名添加前缀,例如:

type Blog struct {
  ID      int
  Author  Author `gorm:"embedded;embeddedPrefix:author_"`
  Upvotes int32
}
// 等效于
type Blog struct {
  ID          int64
    AuthorName  string
    AuthorEmail string
  Upvotes     int32
}

字段标签

声明 model 时,tag 是可选的,GORM 支持以下 tag: tag 名大小写不敏感,但建议使用 camelCase 风格

标签名说明
column指定 db 列名
type列数据类型,推荐使用兼容性好的通用类型,例如:所有数据库都支持 bool、int、uint、float、string、time、bytes 并且可以和其他标签一起使用,例如:not nullsize, autoIncrement… 像 varbinary(8) 这样指定数据库数据类型也是支持的。在使用指定数据库数据类型时,它需要是完整的数据库数据类型,如:MEDIUMINT UNSIGNED not NULL AUTO_INCREMENT
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根据参数创建索引,多个字段使用相同的名称则创建复合索引,查看 索引 获取详情
uniqueIndexindex 相同,但创建的是唯一索引
check创建检查约束,例如 check:age > 13,查看 约束 获取详情
<-设置字段写入的权限, <-:create 只创建、<-:update 只更新、<-:false 无写入权限、<- 创建和更新权限
->设置字段读的权限,->:false 无读权限
-忽略该字段,- 无读写权限
comment迁移时为字段添加注释

关联标签

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

原为链接:https://gorm.io/docs/models.html

GORM 中,关联(Association)功能用于处理模型之间的关系。GORM 支持多种类型的关联,包括 `Has One`、`Belongs To`、`Has Many` 和 `Many To Many`。这些关联可以通过 `Association` 方法进行管理,允许开发者动态地添加、删除或更新关联对象。 ### 1. 定义模型和关联 首先,定义两个模型,并通过 GORM 的标签指定它们之间的关系。例如,考虑一个用户 (`User`) 拥有多个订单 (`Order`) 的情况: ```go type User struct { gorm.Model Name string Orders []Order // 用户拥有多个订单 } type Order struct { gorm.Model UserID uint // 外键,指向 User 表的 ID Price float64 } ``` 在这个例子中,`User` 结构体包含一个 `Orders` 字段,表示该用户拥有的所有订单。而 `Order` 结构体中的 `UserID` 是外键,用于关联到 `User` 表。 ### 2. 使用 `Association` 管理关联 GORM 提供了 `Association` 方法来操作关联数据。以下是一些常见的用法示例: #### 添加关联对象 可以通过 `Append` 方法将一个新的订单添加到用户的订单列表中: ```go user := User{Name: "Alice"} order1 := Order{Price: 100.0} order2 := Order{Price: 200.0} db.Create(&user) db.Create(&order1) db.Create(&order2) // 将 order1 和 order2 添加到 user 的 Orders 关联中 db.Model(&user).Association("Orders").Append(&order1, &order2) ``` #### 删除关联对象 如果需要从用户的订单列表中移除某个订单,可以使用 `Delete` 方法: ```go db.Model(&user).Association("Orders").Delete(&order1) ``` 此操作会从数据库中删除 `user` 与 `order1` 的关联,但不会删除 `order1` 本身。 #### 清空所有关联 如果希望清空某个用户的全部订单,可以使用 `Clear` 方法: ```go db.Model(&user).Association("Orders").Clear() ``` 这将断开用户与所有订单之间的关联,但不会删除订单记录。 #### 查询关联对象 可以通过 `Find` 方法查询某个用户的所有订单: ```go var orders []Order db.Model(&user).Association("Orders").Find(&orders) ``` 此时,`orders` 变量将包含该用户的所有订单。 ### 3. 预加载关联数据 在查询时,可以通过 `Preload` 或 `Joins` 来预加载关联的数据,以避免 N+1 查询问题: ```go var userWithOrders User db.Preload("Orders").Find(&userWithOrders, "id = ?", user.ID) ``` 这样可以在一次查询中获取用户及其所有订单,而不是为每个订单执行单独的查询。 ### 4. 自定义外键 默认情况下,GORM 会自动识别外键字段(如 `UserID`)。但如果需要自定义外键名称,可以在结构体标签中指定: ```go type Order struct { gorm.Model UserID uint `gorm:"column:user_id"` // 自定义外键名为 user_id Price float64 } ``` 此外,还可以通过 `foreignkey` 标签显式声明外键字段: ```go type User struct { gorm.Model Name string Orders []Order `gorm:"foreignkey:CustomerID"` // 指定外键为 CustomerID } type Order struct { gorm.Model CustomerID uint // 外键名改为 CustomerID Price float64 } ``` ### 5. 多对多关联 对于多对多关系,GORM 要求创建中间表来存储双方的主键。例如,用户和角色之间是典型的多对多关系: ```go type User struct { gorm.Model Name string Roles []Role `gorm:"many2many:user_roles;"` } type Role struct { gorm.Model Name string Users []User `gorm:"many2many:user_roles;"` } ``` 在这种情况下,`user_roles` 是中间表,存储用户和角色的关联。 ### 6. 使用 `Association` 进行批量操作 除了单个关联操作,`Association` 还支持批量操作。例如,可以一次性替换某个用户的全部订单: ```go newOrders := []Order{ {Price: 300.0}, {Price: 400.0}, } db.Model(&user).Association("Orders").Replace(&newOrders) ``` 这将先删除原有的订单关联,然后将新的订单列表插入进去。 ### 总结 GORM 的 `Association` 功能提供了灵活的方式来管理模型之间的关系。无论是简单的 `Has One` 或 `Belongs To`,还是复杂的 `Many To Many` 关系,都可以通过 `Association` 方法轻松实现。结合 `Preload`、`Append`、`Delete`、`Clear` 和 `Replace` 等方法,开发者能够高效地操作关联数据[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

多课网_老郭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值