GORM操作数据库 | 青训营笔记

134 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第5篇笔记。

上一篇笔记记录了GORM框架的一些基本介绍,本篇笔记记录一下GORM框架操作数据库的一些方法。

新增记录

常规指针创建

user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}

result := db.Create(&user) // 通过数据的指针来创建

user.ID             // 返回插入数据的主键
result.Error        // 返回 error
result.RowsAffected // 返回插入记录的条数

指定某些字段插入

//指定插入某些字段插入
db.Select("Name", "Age", "CreatedAt").Create(&user)
//指定某些字段不插入
db.Omit("Name", "is_delete", "CreatedAt").Create(&user)

删除记录

  • 删除操作可以在 model 上绑定一些hook函数,做前置检查,例如不能删除 admin账号等
  • 另外可以在模型定义的时候指定软删除字段,这样在执行删除操作的时候会对应转换为 update 操作
// 根据主键删除 DELETE FROM `sys_user_info` WHERE `sys_user_info`.`id` = 4
config.Db.Delete(&model.SysUserInfo{}, 4)
// 根据其它条件删除 DELETE FROM `sys_user_info` WHERE `user_name` = 'lll'
config.Db.Where("user_name", c.Query("user_name")).Delete(&model.SysUserInfo{})

修改记录

  • 修改操作同样可以在model上绑定一些hook函数,例如 BeforeUpdate BeforeSave
  • UpdateColumn/UpdateColumns 可跳过hook 函数与自动更新时间,类似于原生的sql操作
  • 注意在指定修改的模型时,如果将主键字段已经赋值的话一定会加入到where语句中
  • Updates使用的参数是model的话则不会更新默认值,如果需要默认值需要改成map[string]interface{},其中key为数据库中更新的列名称

根据主键修改

user := &model.SysUserInfo{}
user.ID = 1
// UPDATE `sys_user_info` SET `sys_utime`='2021-08-08 16:46:15.752',`user_name`='lll',`user_addr`='wuxi' WHERE `id` = 1
config.Db.Model(&user).Updates(model.SysUserInfo{UserName: "lll", UserAddr: "wuxi"})

根据其它条件修改

// 根据主键更新多列
user := &model.SysUserInfo{}
user.ID = 1
// 根据其它条件更新 UPDATE `sys_user_info` SET `sys_utime`='2021-08-08 16:46:15.754',`user_name`='小皮球',`user_addr`='深圳' WHERE user_addr = 'shenzhen'
config.Db.Model(&model.SysUserInfo{}).Where("user_addr = ?", "shenzhen").Updates(model.SysUserInfo{UserName: "小皮球", UserAddr: "深圳"})
// Omit 指定忽略Updates中map的指定的那些key更新 UPDATE `sys_user_info` SET `user_age`=18,`sys_utime`='2021-08-08 16:46:15.755' WHERE `id` = 1
config.Db.Model(&user).Omit("user_name").Updates(map[string]interface{}{"user_name": "小小飞", "user_age": 18})
// Select 指定 Updates 中的map只有哪些key更新 UPDATE `sys_user_info` SET `sys_utime`='2021-08-08 16:46:15.756',`user_name`='new_name',`user_age`=47 WHERE `id` = 1
config.Db.Model(&user).Select("user_name", "user_age").Updates(model.SysUserInfo{UserName: "new_name", UserAge: 47})

查询记录

  • scan类似Find都是用于执行查询语句,然后把查询结果赋值给结构体变量,区别在于scan不会从传递进来的结构体变量提取表名。使用 Scan 方法的时候需要我们显示指定数据库的表名。另外回调函数注册的不一样,Find 函数支持更多的 Callback 注入。

普通查询

var userList []*model.SysUserInfo
//返回的是全部字段
config.Db.Where("user_name = ?", userName).Find(&userList)
// 原生 SQL
db.Raw("SELECT * FROM sys_user_info WHERE name = ?", userName).Scan(& userList)

返回指定字段

var userList []*model.SysUserInfo
config.Db.Select("user_name", "id").Where("user_name = ?", userName).Find(&userList)

排序

var userList []*model.SysUserInfo
// 查询后排序
config.Db.Where("user_name = ?", c.Query("user_name")).Order("user_age").Order("sys_ctime desc").Find(&userList)

分页

var userList []*model.SysUserInfo
// 分页查询 SELECT * FROM `sys_user_info` WHERE user_age > 10 LIMIT 3 OFFSET 2;
config.Db.Where("user_age > 10").Offset(2).Limit(3).Find(&userList)

group 与 Having

type Result struct {
   Sex   int8
   Count int
}
var result []*Result
// Model 一定要指定,否则会以默认规则 results 为表名查找,或者 struct 绑定方法 TableName
config.Db.Model(&model.SysUserInfo{}).Select("user_sex as Sex", "count(*) as count").Group("user_sex").Having("count(*) > 1").Find(&result)

distinct

// distinct SELECT DISTINCT `user_name` FROM `sys_user_info` WHERE user_sex = 1
config.Db.Where("user_sex = 1").Distinct("user_name").Find(&userList)

join

var userList []*model.SysUserInfo
// join SELECT a.user_name,b.user_age FROM sys_user_info a left join sys_user_info b on a.user_id = b.user_id WHERE `a`.`user_name` = '猪八戒'
config.Db.Table("sys_user_info a").Select("a.user_name", "b.user_age").Joins("left join sys_user_info b on a.user_id