定义
Gorm 是一个功能强大的 Go ORM 框架,是链式调用的
操作语法
创建一个数据库的连接
Gorm是使用dns来进行连接的
var db *gorm.DB
func Init() error {
var err error
dsn := "root:123456@tcp(127.0.0.1:3306)/gowebtry?charset=utf8mb4&parseTime=True&loc=Local"
db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
return err
}
增删改查
db 对象的方法与数据库的常见操作(UPDATE、DELETE、SELECT、INSERT)是一一对应的
db.Clauses
在 Gorm 中,db.Clauses 并不直接对应传统的 SQL 操作(INSERT、SELECT、UPDATE、DELETE),而是一个功能性扩展,用于在这些操作中动态添加或修改 SQL 子句(Clause)
db.Clauses(clause.Limit{Limit: 10}).Find(&users)
在查询中添加 LIMIT 10 子句,限制查询结果为 10 条。
用clause.OnConflict处理数据冲突
clause.OnConflict 支持指定冲突字段、更新字段、忽略操作等,满足各种场景需求:
- 插入时忽略冲突。
- 冲突时更新指定字段。
- 自定义冲突处理逻辑。 比如这样
db.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "id"}}, // 指定冲突字段
DoUpdates: clause.AssignmentColumns([]string{"name", "age"}), // 冲突时更新的字段
}).Create(&User{ID: 1, Name: "Bob", Age: 30})
- 如果
ID = 1不存在,插入记录{ID: 1, Name: "Bob", Age: 30}。 - 如果
ID = 1已存在,则更新其name和age字段。
使用的小坑
First的使用踩坑
使用 First时,需要注意查询不到数据会返回ErrRecordNotFound.使用 Find 查询多条数据,查询不到数据不会返回错误。
使用结构体作为查询条件
当使用结构作为条件查询时,GORM只会查询非零值字段,因为0还有无效值的含义,GORM无法分辨究竟是0还是无效值的意思,所以就直接选择忽略了,如果我们的字段是0或者false或者其他零值,该字段不会被用来构建查询条件,如果要用的话用Map来构建
软删除
GORM 默认通过一个名为 gorm.DeletedAt 的字段实现软删除。当该字段值为 NULL 时,表示记录有效;当它被赋值为时间戳时,表示记录已被删除
type User struct {
ID uint
Name string
DeletedAt gorm.DeletedAt `gorm:"index"`
}
通过调用 GORM 的 Delete 方法删除记录时,GORM 不会真正执行 DELETE SQL,而是更新 DeletedAt 字段为当前时间。
db.Delete(&user)
之后查询的时候会排除DeletedAt不是空的数据,从而实现软删的 效果
可以通过更新 DeletedAt 字段为 NULL 恢复软删除记录
db.Model(&user).Update("DeletedAt", nil)
事务
Gorm 提供了Begin、Commit、Rollback方法用于使用事务
(事务是用来确保一组数据库操作要么全部成功,要么全部失败的机制。通过使用事务,能够保证数据一致性,尤其是在多个表之间存在复杂关联操作时)
Tansaction避免漏写Commit、Rollbcak
db.Transaction(func(tx *gorm.DB) error {
// 在这里写所有的事务操作
// 使用 tx 而不是 db 并且tx := db.Begin()
if err := tx.Create(&Order{UserID: 1, TotalAmount: 100}).Error; err != nil {
return err // 返回错误会触发回滚
}
if err := tx.Model(&Product{}).Where("id = ?", 1).Update("stock", gorm.Expr("stock - ?", 1)).Error; err != nil {
return err // 返回错误会触发回滚
}
return nil // 返回 nil 会触发提交事务
})
Hook回调函数
回调函数允许你在执行数据库操作时插入自定义逻辑,比如数据验证、默认值填充、日志记录等。
Hook 提供了一种机制,让开发者可以在事件的前后添加自定义逻辑:
- 数据操作前:在执行操作前修改或验证数据。
- 数据操作后:在操作完成后触发逻辑,例如清理、日志记录或通知。
Gorm性能提高
对于写操作(创建、更新、删除),为了确保数据的完整性,GORM会将它们封装在事务内运行。但这会降低性能,你可以使用 SkipDefaultTransaction关闭默认事务。
使用 PrepareStmt 缓存预编译语句可以提高后续调用的速度,本机测试提高大约 35 %左右。