开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第23天,点击查看活动详情
今天接着学习Go的Gorm框架来操作数据库,今天来介绍CRUD的四种基本写法,这是一个非常对开发人员非常友好的ORM库,和我一起来学习下吧!
CRUD接口
创建
以User结构体为例子,来创建一条记录
user := User{Name: "YYQQ", Age: 18, Birthday: time.Now()}
//批量插入
var users = []User{{Name: "YYQQ1"}, {Name: "YYQQ2"}, {Name: "YYQQ3"}}
db.Create(&users)
db.NewRecord(user) // => 返回 `true` ,因为主键为空
db.Create(&user) //传入结构体的指针
db.NewRecord(user) // => 在 `user` 之后创建返回 `false`
NewRecord()来判断是否存在相同主键
通过标签定义default来设置字段的默认值,如下所示:
type User struct {
ID int64
Name string `gorm:"default:'YYQQ'"`
Age int64
}
SQL会排除那些没有值或者有零值的字段,在记录插入数据库之后,gorm将从数据库中加载这些字段的值
var user = User{Age: 12, Name: ""}
db.Create(&animal)
//user.Name => 'YYQQ'
需要注意的是,所有包含零值的字段,例如 0,'',false 或者其他的 零值 不会被保存到数据库中,但是会使用该字段的默认值
可以使用指针类型或者其他的值,就可以避免使用默认值
type User struct {
ID int64
Name *string `gorm:"default:'YYQQ'"`
Age int64
}
更新
通过Save方法在执行SQL更新操作的时候,会将所有字段一起更新,即使这个字段没有被修改
user.Name = "YYQQ_2"
user.Age = 100
db.Save(&user)
如果不想更新全部字段,可以使用Update,Updates方法来更新修改的字段
// 如果单个属性被更改了,更新它,根据它的主键ID进行更改
db.Model(&user).Update("name", "YYQQ")
// 根据Model的值和where条件进行组合更新
db.Model(&user).Where("age = ?", 12).Update("name", "YYQQ")
// 使用 `map` 更新多个属性,只会更新那些被更改了的字段
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
// 使用 `struct` 更新多个属性,只会更新那些**被修改了**的和**非空的字段**
db.Model(&user).Updates(User{Name: "hello", Age: 18})
// 当使用结构体更新的时候, GORM 只会更新那些非空的字段
// 例如下面的更新,没有东西会被更新,因为像 "", 0 都是这些字段类型的空值
db.Model(&user).Updates(User{Name: "", Age: 0})
更新选中的字段或者忽略某些字段,就是用Select、Omit方法
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18})
//只更新name = "hello"
db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18})
//只更新age = 18 不更新name
带有表达式的SQL更新,通过gorm.Expr来计算带有表达式的值
db.Model(&product).Update("price", gorm.Expr("price * ? + ?", 4, 21))
db.Model(&product).Updates(map[string]interface{}{"price": gorm.Expr("price * ? + ?", 2, 100)})
db.Model(&product).UpdateColumn("quantity", gorm.Expr("quantity - ?", 1))
db.Model(&product).Where("quantity > ?", 1).UpdateColumn("quantity", gorm.Expr("quantity - ?", 1))
删除
这里需要注意,GORM删除一条记录是根据主键是否为空来进行删除,如果主键字段为空,则会删除模型中所有的值,反之删除对应主键的值
// 删除一条存在的记录
db.Delete(&user)
// DELETE from user where id=10;
批量删除所有匹配的记录
db.Where("name LIKE ?", "%YYQQ%").Delete(User{})
// DELETE from users where name LIKE "%YYQQ%";
db.Delete(User{}, "name LIKE ?", "%YYQQ%")
// DELETE from users where name LIKE "%YYQQ%";
软删除,因为gorm.Model中有DeleteAt字段,它将拥有软删除的功能,真正删除的时候,数据不会被永久删除,而是将DeleteAt字段更新为当前时间,并且删除后的记录需要通过Unscoped方法查找
db.Delete(&user)
// UPDATE users SET deleted_at="xxxx" WHERE id = xxx;
// 批量删除
db.Where("age = ?", 20).Delete(&User{})
// UPDATE users SET deleted_at="xxxx" WHERE age = 20;
// 在查询记录时,软删除记录会被忽略
db.Where("age = 20").Find(&user)
// SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;
// 使用 Unscoped 方法查找软删除记录
db.Unscoped().Where("age = 20").Find(&user)
// SELECT * FROM users WHERE age = 20;
// 使用 Unscoped 方法永久删除记录
db.Unscoped().Delete(&user)
// DELETE FROM users WHERE id=10;
查询
以下代码展示如何获取第一条记录,最后一条记录:
// 获取第一条记录,按主键排序
db.First(&user)
// SELECT * FROM users ORDER BY id LIMIT 1;
// 获取一条记录,不指定排序
db.Take(&user)
// SELECT * FROM users LIMIT 1;
// 获取最后一条记录,按主键排序
db.Last(&user)
//// SELECT * FROM users ORDER BY id DESC LIMIT 1;
// 通过主键进行查询 (仅适用于主键是数字类型)
db.First(&user, 10)
// SELECT * FROM users WHERE id = 10;
通过原生SQL进行查询操作
// 获取第一条匹配的记录
db.Where("name = ?", "YYQQ").First(&user)
// SELECT * FROM users WHERE name = 'YYQQ' limit 1;
// 获取所有匹配的记录
db.Where("name = ?", "YYQQ").Find(&users)
// SELECT * FROM users WHERE name = 'YYQQ';
// <> 不等于
db.Where("name <> ?", "YYQQ").Find(&users)
// IN 范围
db.Where("name in (?)", []string{"YYQQ", "YYQQ 2"}).Find(&users)
// LIKE 模糊查询
db.Where("name LIKE ?", "%YYQQ%").Find(&users)
// AND 并集
db.Where("name = ? AND age >= ?", "YYQQ", "22").Find(&users)
// Time 时间
db.Where("updated_at > ?", lastWeek).Find(&users)
// BETWEEN 区间
db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)
也可以通过 结构体 和 Map 进行查询
// Struct
db.Where(&User{Name: "YYQQ", Age: 20}).First(&user)
// SELECT * FROM users WHERE name = "YYQQ" AND age = 20 LIMIT 1;
// Map
db.Where(map[string]interface{}{"name": "YYQQ", "age": 20}).Find(&users)
// SELECT * FROM users WHERE name = "YYQQ" AND age = 20;
// 多主键 slice 查询
db.Where([]int64{1, 2, 3}).Find(&users)
// SELECT * FROM users WHERE id IN (1, 2, 3);
总结
今天浅谈了Go与Gorm(三),主要介绍了数据库的CRUD操作,接下来会继续深入了解GORM的相关知识,对于一个刚入门的我来说,还有许多地方需要学习,有错误的地方欢迎大家指出,共同进步!!