浅谈Go与Gorm(三)

384 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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})

更新选中的字段或者忽略某些字段,就是用SelectOmit方法

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的相关知识,对于一个刚入门的我来说,还有许多地方需要学习,有错误的地方欢迎大家指出,共同进步!!