记录Gorm学习手册
声明模型
模型定义
GORM通过将Go结构体(Go Structs)映射到数据库表来简化数据库交互
模型定义
模型是使用普通结构体定义的。这些结构体可以包含具有基本Go类型、指针或这些类型的别名, 甚至是自定义类型(只需要实现database/sql
包中的Scanner和Valuer接口)。
考虑以下user
模型示例:
1 | type User struct { |
在此模型中:
- 具体数字型如
uint
、string
和uint8
直接使用; - 指向
*string
和*time.Time
类型的指针表示可空字段; - 来自
database/sql
包的sql.NullString
和sql.NullTime
用于具有更多控制的可空字段; CreateAt
和UpdateAt
是特殊字段, 当记录被创建或更新时, GORM会自动向内填充当前时间;
除了GORM中模型声明的基本特性外, 强调下通过serializer标签支持序列化也很重要; 此功能增强了数据存储和检索的灵活性, 特别是需要自定义序列化逻辑的字段;
约定
- 主键: GORM使用一个名为
ID
的字段作为每个模型的默认主键; - 表名: 默认情况下, GORM将结构体名称转化为
snake_case
并为表名加上复数形式; 例如, 一个User
结构体在数据库中表名变成users
; - 列名: GORM自动将结构体字段名转换为
snake_case
作为数据库中列名; - 时间戳字段: GORM使用字段
CreatedAt
和UpdatedAt
来自动跟踪记录的创建和更新时间;
gorm.Model
GORM提供了一个预定义的结构体, 名为gorm.Model
, 其中包含常用字段:
1 | // gorm.Model 的定义 |
- 将其嵌入在结构体中: 可以直接在结构体中嵌入
gorm.Model
, 以便自动包含这些字段; - 包含的字段:
ID
: 每个记录的唯一标识符(主键);CreatedAt
: 在创建时自动设置为当前时间;UpdatedAt
: 每当记录更新时, 自动更新为当前时间;DeletedAt
: 用于软删除;
CRUD接口
创建
创建记录
1 | user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()} |
我们还可以使用Create()
创建多项记录:
1 | users := []*User{ |
无法向create
传递结构体, 所以应该传入数据的指针
用指定的字段创建记录
创建记录并为指定字段赋值
1 | db.Select("Name", "Age", "CreateAt").Create(&user) |
创建记录并忽略传递给Omit
的字段值
1 | db.Omit("Name", "Age", "CreateAt").Create(&user) |
批量插入
要高效地插入大量记录, 请将切片传递给Create
方法。GORM将生成一条SQL来插入所有数据, 以返回所有主键值, 并触发Hook
方法, 当这些记录可以被分割成多个批次时, GORM会开启一个事务来处理它们。
1 | var users = []User{ |
可以通过db.CreateInBatches
方法来指定批量插入的批次大小
1 | var users []User{ |
注意: 使用CreateBatchSize
选项初始化GORM实例后, 此后进行创建&关联操作时所有的INSERT
行为都会遵循初始化的配置。
1 | db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{ |
创建钩子
GORM允许用户通过实现这些接口BeforeSave
、BeforeCreate
、AfterSave
、AfterCreate
来自定义钩子。这些钩子方法会在创建一条记录时被调用;
1 | func (u *User) BeforeCreate (tx *gorm.DB) (err error) { |
如果想跳过Hooks
方法, 可以使用SkipHooks
会话模式, 例子如下:
1 | DB.Session(&gorm.Session{SkipHooks: true}).Create(&user) |
根据 Map 创建
GORM支持通过map[string]interface{}
与[]map[string]interface{}{}
来创建记录。
1 | db.Model(&User{}).Create(map[string]interface{ |
注意: 当使用map来创建时, 钩子方法不会执行, 关联不会被保存且不会回写主键。