这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天
Gorm
官方文档:gorm.cn/zh_CN/docs/…
Gorm的默认约定
- Gorm使用名为ID的字段 作为主键
- 使用结构体的蛇形负数作为表名,字段名的蛇形作为列名
- 使用CreatedAt、UpdateAt作为创建、更新时间
1. 定义Gorm Model 和 连接到数据库
1.1 定义Model
gorm.Model
type Model struct {
ID uint `gorm:"primarykey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt DeletedAt `gorm:"index"`
}
example:
type Product struct {
gorm.Model
Code string
Price uint
}
2.1 连接到数据库
dsn := "root:123456@tcp(127.0.0.1:3306)/gorm?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
迁移 ------ AutoMigrate
AutoMigrate 用于自动迁移您的 schema(架构、模式:在数据库系统中是形式语言描述的一种结构,是对象的集合),保持您的 schema 是最新的。
注意: AutoMigrate 会创建表、缺失的外键、约束、列和索引。 如果大小、精度、是否为空可以更改,则 AutoMigrate 会改变列的类型。 出于保护您数据的目的,它 不会 删除未使用的列
db.AutoMigrate(&User{})
db.AutoMigrate(&User{}, &Product{}, &Order{})
2. CURD
users :=make([]*User, 10)
当使用结构体作为条件进行操作时,GORM只会查询非零值字段。如果要以操作零值的话,应该使用Map来进行操作。
-
Create
可以通过
default标签定义默认值//Create //插入一条数据 p := &Product{Code: "D41"} db.Create(p) //插入多条数据 products := []*Product{{Code: "D42"}, {Code: "D43"}, {Code: "D44"}} db.Create(products) -
Update
//Update //更新单字段 db.Model(&User{ID: 111}).Where("age > ?", 18).Update("name", "hello") //更新多个字段(结构体:不更新零值) db.Model(&User{ID: 111}).Updates(User{Name: "hhh", Age: 18}) //更新多个字段(map:更新零值) db.Model(&User{ID: 111}).Updates(map[string]interface{}{"name": "hhh", "age": 18}) //SQL表达式更新 db.Model(&Product{Model: gorm.Model{ID: 111}}).Update("price", gorm.Expr("price * ? + ?", 2, 100)) -
Read
尽量不要使用First
//Read db.Where("age > 10").Find(&users) db.Where("name IN ?", []string{"jinzhu", "jinzhu 2"}).Find(&users) db.Where("name LIKE ?", "%jin%").Find(&users) db.Where("name = ? AND age > ?", "jinzhu", "22").Find(&users) db.Where(&User{Name: "jinzhu", Age: 0}).Find(&users) db.Where(map[string]interface{}{"Name": "jinzhu", "Age": 0}).Find(&users) -
Delete
- GORM提供了gorm.DeletedAt(包含该字段)用于帮助用户实现软删。
- 拥有软删能力的Model调用Delete时,记录不会被从数据库中真正删除。但GORM会将DeletedAt置为当前时间,并且你不能再通过正常的查询方法找到该记录。
- 使用Unscoped可以查询到被软删的数据。
查找被软删的记录:
db.Unscoped().Where("age = 20").Find(&users)永久删除:
db.Unscoped().Delete(&order)//Delete //删除条件中包含主键 db.Delete(&p) db.Where("name = ?", "jinzhu").Delete(&products) db.Delete(&User{}, 10) db.Delete(products, []int{1, 2, 3}) //删除条件中不包含主键,执行批量删除 db.Where("name like ?", "%y%").Delete(&User{})
3. 事务与HOOK
3.1 事务
要在事务中执行一系列操作,一般流程如下:
db.Transaction(func(tx *gorm.DB) error {
// 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')
if err := tx.Create(&People{Name: "Giraffe"}).Error; err != nil {
// 返回任何错误都会回滚事务
return err
}
if err := tx.Create(&People{Name: "Lion"}).Error; err != nil {
return err
}
// 返回 nil 提交事务
return nil
})
3.2 HOOK
- Hook 是在创建、查询、更新、删除等操作之前、之后调用的函数。
- 如果您已经为模型定义了指定的方法,它会在创建、更新、查询、删除时自动被调用。如果任何回调返回错误,GORM 将停止后续的操作并回滚事务。
- 钩子方法的函数签名应该是
func(*gorm.DB) error
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
}
func (u *User) AfterCreate(tx *gorm.DB) (err error) {
}
......