01
概念
在项目开发中,数据库写操作包含新增、删除和修改,使用 GORM V2 可以更加安全和便捷进行写操作。
02
新增
普通创建
使用 GORM V2 创建记录,可以定义一个自定义结构体类型的变量,调用 Create 方法,通过入参结构体类型变量的指针来创建记录。
stu := Student{ Name: "rose", Age: 28, Email: "rose@88.com", } result := gormDB.Create(&stu)
通过获取变量的 ID,可以得到插入记录的主键 ID。
insertID := stu.ID fmt.Printf("主键 ID:%d\n", insertID)
通过调用 Error 和 RowsAffected,可以分别获取插入错误和插入行数。
insertErr := result.Error fmt.Printf("插入错误:%v\n", insertErr) num := result.RowsAffected fmt.Printf("影响行数:%d\n", num)
GORM V2 新增了选定字段和排除字段创建
选定字段创建 Select
gormDB.Select("Name", "Age").Create(&stu)
排除字段创建 Omit
gormDB.Omit("Age", "Email").Create(&stu)
批量创建
定义一个切片变量,通过调用 Create 方法,入参切片类型的变量,GORM 会生成一个单一的 sql 语句来插入所有数据,并回填主键的值。
stus := []Student{ { Name: "coco", Age: 19, Email: "coco@88.com", }, { Name: "bear", Age: 12, Email: "bear@88.com", }, } gormDB.Create(&stus) for _, stu := range stus { fmt.Printf("ID:%d\n", stu.ID) }
GORM 支持根据 map 创建记录
根据 map 单条创建
stus := []Student{ { Name: "coco", Age: 19, Email: "coco@88.com", }, { Name: "bear", Age: 12, Email: "bear@88.com", }, } gormDB.Create(&stus) for _, stu := range stus { fmt.Printf("ID:%d\n", stu.ID) }
根据 map 批量创建
stusMap := []map[string]interface{}{ { "Name": "apple", "Age": 20, "Email": "apple@88.com", }, { "Name": "pear", "Age": 21, "Email": "pear@88.com", }, } gormDB.Model(&Student{}).Create(stusMap)
需要注意的是,根据 map 创建,不会自动填充 gorm.Model 结构体定义的字段。
可以使用 GORM 标签 default 设置默认值,插入数据时,设置的默认值会被用于填充值为零值的字段。
需要注意的是,如果默认值本身是数据类型的零值,将不会被保存到数据库。对于数据库表的设置默认值的字段,需要预先在声明模型的 struct 字段上使用标签 default 设置默认值,否则会插入该字段数据类型的零值。
03
删除
单条删除
删除单条记录,删除对象需要指定主键,否则会触发批量删除并且会被阻止全局删除功能拦截。
stu := Student{} stu.ID = 16 gormDB.Delete(&stu)
根据主键删除
GORM 支持根据内联条件指定删除对象的主键,但是只支持数据类型为整型主键。
gormDB.Delete(&Student{}, 2) gormDB.Delete(&Student{}, "2") gormDB.Delete(&Student{},[]int{8,9})
批量删除
GORM 可以根据指定的删除条件,批量删除全部匹配的记录。
gormDB.Where("email LIKE ?", "%88%").Delete(Student{}) gormDB.Delete(Student{}, "email LIKE ?", "%88%")
阻止全局删除
如果没有指定 WHERE 条件,GORM 不会执行删除操作,并返回 ErrMissingWhereClause 错误。
如果想要全局删除,必须指定 WHERE 条件,或者执行原生 SQL,或者启用 AllowGlobalUpdate 模式。
软删除
如果模型包含 gorm.DeletedAt 字段,将会启用软删除,软删除是指不会真的删除记录,而是会将 DeletedAt 字段设置为当前时间,并且被软删除的记录,不可以通过正常查询操作获取。
如果需要查询被软删除的记录,需要使用 Unscoped 方法。
永久删除
永久删除记录,也需要使用 Unscoped 方法。
gormDB.Unscoped().Where("id = ?", 5).Delete(&Student{}) gormDB.Unscoped().Where("id IN ?", []int{8,9}).Delete(&Student{})
04
修改
保存所有字段
调用 Save 方法更新数据,会保存所有字段,即使字段的值为字段类型的零值。
student := Student{} gormDB.First(&student) student.Name="cat1" student.Age=0 student.Email="cat1@88.com" gormDB.Save(&student)
更新单个列
使用 Update 方法更新单个列时,需要指定条件,否则会返回 ErrMissingWhereClause 的错误。
student := Student{} student.ID = 15 gormDB.Model(&student).Update("email", "cat@gmail.com") gormDB.Model(&Student{}).Where("age = ?", 19).Update("age", 21)
当使用 Model 方法时,并且该对象的主键有值,该值会被用于更新条件。
student := Student{} student.ID = 15 gormDB.Model(&student).Where("email = ?", "cat@gmail.com").Update("name", "bigFace")
更新多个列
使用 Updates 方法更新多个列,GORM 支持 struct 和 map[string]interface{} 参数,需要注意的是,当使用 struct 作为参数时,GORM 只会更新字段的值不是字段类型的零值的字段。
struct
student := Student{} student.ID = 1 gormDB.Model(&student).Updates(Student{Name: "book", Age: 20})
map
student := Student{} student.ID = 15 gormDB.Model(&student).Updates(map[string]interface{}{"name" : "panda", "age": 30})
更新选定或排除字段
更新操作,也支持根据选定或排除字段进行更新。
选定字段 Select
student := Student{} student.ID = 2 gormDB.Model(&student).Select("name").Updates(map[string]interface{}{"name":"lucy", "email":"lucy@88.com"})
排除字段 Omit
student := Student{} student.ID = 3 gormDB.Model(&student).Omit("name").Updates(map[string]interface{}{"name": "dog", "age": 29, "email":"dog@gmail.com"})
批量更新
如果未通过 Model 方法指定记录的主键,GORM 则会执行批量更新。
struct
gormDB.Model(&Student{}).Where("name=?", "milk").Updates(Student{Name: "tom", Age: 18})
map
gormDB.Model(&Student{}).Where("name = ?", "frank").Updates(map[string]interface{}{"name":"milk", "email": "milk@88.com"}) gormDB.Table("students").Where("name = ?", "tom").Updates(map[string]interface{}{"name":"honey", "email" :"honey@88.com"})
阻止全局更新
如果未指定任何条件执行批量更新,默认情况下,GORM 不会执行该操作,并且会返回 ErrMissingWhereClause 错误。
如果希望执行全局更新,需要指定条件,或使用原生 SQL,或启用 AllowGlobalUpdate 模式。
更新的记录数和更新操作的错误
获取受影响的行数和更新操作的错误。
result := gormDB.Table("students").Where("name = ?", "honey").Updates(map[string]interface{}{"name":"life", "email" :"life@88.com"}) rows := result.RowsAffected fmt.Printf("更新的记录数:%d\n", rows) fmt.Println(result.Error)