这是我参与「第三届青训营 -后端场」笔记创作活动的的第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