这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
Gorm框架
基本使用
定义数据模型 与 数据表名:
type Product struct{
Code string
Price uint
}
//为数据模型定义表的名字
func (p Product) TableName() string{
return "product"
}
对于数据模型与其对应的数据表和字段,gorm有如下的默认约定:
- 使用名字为ID的字段作为表的主键
- 使用结构体的蛇形复数作为表名(例如表名
visit_logs) - 使用字段的蛇形作为列名
- 使用CreateAt和UpdateAt两个字段来跟踪对象创建和修改的时间
可以使用结构体的tag来指定字段对应的列名,以及默认值等。
连接到数据库:
gorm支持多种类型的数据库(MySql,PostgreSql,SQlite和SQL Server),通过给对应的驱动程序传递一个dsn的方式打开连接
import(
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main(){
dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err:= gorm.Open(mysql.Open(dsn), &gorm.Config{})
}
对于数据库连接池,GORM使用标准库的database/sql维护
创建数据
使用db.Create(&User{Name:"Jim", Age: 18})来在数据库中创建一条记录。
注意db.Create被调用是,这条Sql已经生成了,因此无法在它后面加.Where字句作为条件,如果需要解决冲突,使用如下的形式:
db.Clause(clause.OnConflict{DoNothing: true}).Create(&p)
查询
-
检索单个对象
GORM提供First/Take/Last三个方法从数据库中检索单个对象,分别对应主键升序第一条记录、未排序的一条记录和主键升序的最后一条记录。这三个方法会为生成的SQL添加
LIMIT 1条件。对于传入的参数,如果主键已经被设置了,那么会使用主键作为查询条件。
db.First(&user) db.Take(&user) db.Last(&user)也可以传入额外的参数作为查询条件。
- First方法的一个坑点是:如果查询不到数据时,会返回ErrRecordNotFound
-
检索全部对象
使用
db.Find检索全部的对象。在查询不到数据时不会返回数据。var users []User db.Find(&users) -
增加检索条件
使用
db.Where方法来为一条查询语句增加检索条件。
更新数据
-
更新单个字段
使用
db.Model(&user).Update(“name", "hello")来更新数据,即这条语句会根据user的主键(如果存在非零的主键ID)找到并更新对应记录的name字段为hello使用Model是为了传递数据表名数据。
-
更新多个字段
使用
db.Model(&user).Updates(map[string]any{"name":"hello", "age": 0})来同时更新多个字段值。需要注意的是如果给Updates传入的参数是结构体而不是map,那么其中的零值是不会更新的。
删除数据
使用db.Delete(&user, conds...)来删除字段。
如果在数据模型中增加一个Deleted gorm.DeletedAt字段,可以实现数据的软删除。
软删除的数据不会从数据库中真正删除,但是用GORM的常规查询方法无法再查询到软删除的数据,需要使用Unscoped来查询被软删除的数据。
事务处理
GORM提供了Begin、Commit和Rollback方法用于处理事务。
一个例子如下:
tx := db.Begin() // 开始事务处理
if err:= tx.Create(&User{Name:"name"}).Error; err!= nil{
tx.Rollback()
return
}
if err:= tx.Create(&User{Name:"name2"}).Error; err!= nil{
tx.Rollback()
return
}
tx.Commit()
事务的自动处理
如果使用GORM提供的Transaction方法,可以自动提交事务,避免漏掉Commit和Rollback
推荐使用Transaction方法来代替上述的Begin/Commit/Rollback手动调用,以减少错误的发生
Hook
给结构体增加类似于BeforeCreate(tx *gorm.DB)(err error)方法来提供在对象的增删改查前后自动调用的函数。
GORM会给Hook提供一个默认事务,因此任何Hook返回错误时,GORM会停止后续操作并回滚事务。
提高性能的手段
-
关闭事务处理
对于数据的写操作,为了保证数据的完整性,GORM默认会将它们封装到事务内运行。
可以使用SkipDefaultTransaction来关闭默认事务
-
使用PrepareStmt缓存预编译语句
可以提高后续的调用大约35%的性能。
GORM扩展
- 代码生成
- 分片
- 手动索引
- 乐观锁
- 读写分离
都在github.com/go-gorm下有对应的仓库。