GORM基础用法介绍(二) | 青训营笔记

136 阅读4分钟

这是我参与「第五届青训营」伴学笔记创作活动的第8天。

这是GORM系列的第二篇文章,通过上一篇文章介绍GORM是什么、怎么连接数据库之后,这篇文章将会介绍使用GORM进行基本的CRUD操作的方法。

连接到数据库,GORM会返回一个*gorm.DB类型的指针,通过这个指针指向的gorm.DB对象(下文称db变量),就可以进行数据库操作。

创建数据

通过db变量创建数据,需要借助于Create()方法,如下所示:

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

result := db.Create(&user)

User结构体是一个GORM模型结构体,将相应字段的值填入一个结构体变量,然后调用db变量的Create方法传入该结构体变量的指针,Create方法将会把一条相应的记录加入到对应的表中(通过GORM模型结构体找到表名,通过结构体的注解找到相应的字段)。如果有些字段是自动生成的(例如设置了自增的主键),则无需手动写入值到结构体变量中。在完成这一操作后,GORM将会返回一个结果(上面代码中的result),通过这个结果,调用者可以了解到是否发生错误、插入记录的条数等信息。此外,因为用户传入Create方法的是指针,GORM会在添加记录后把记录的所有字段填回到传入的变量中,这样调用者就可以知道一些自动生成字段的值,如下:

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

查询数据

GORM提供了FirstTakeLast方法,以便从数据库中检索单个对象。当查询数据库时它添加了LIMIT 1条件,且没有找到记录时,它会返回ErrRecordNotFound错误,例子如下所示:

// 获取第一条记录(主键升序)
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;

result := db.First(&user)
result.RowsAffected // 返回找到的记录数
result.Error        // returns error or nil

// 检查 ErrRecordNotFound 错误
errors.Is(result.Error, gorm.ErrRecordNotFound)

如果要查询多条记录或者不希望在未找到记录时不返回ErrRecordNotFound错误,可以使用Find方法,它不但接受单个GORM模型结构体变量的指针,也接受切片类型,如果传入的是切片类型,Find方法将会把所有找到的符合条件的记录放进切片里。下面是一些使用的例子:

var users []User
db.Find(&users, []int{1,2,3})
// SELECT * FROM users WHERE id IN (1,2,3);

// Get all records
result := db.Find(&users)
// SELECT * FROM users;

在进行数据库操作时,可以使用Where方法来指定条件,条件以字符串的形式表达,可以使用?作为格式化符号来嵌入变量,例如:

// Get all matched records
db.Where("name <> ?", "jinzhu").Find(&users)
// SELECT * FROM users WHERE name <> 'jinzhu';

更新数据

更新数据可以使用Update方法,当使用Update更新单列时,需要有一些条件,否则将会引起ErrMissingWhereClause错误,Update的参数是要更新的字段名和值,如下所示:

// 条件更新
db.Model(&User{}).Where("active = ?", true).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE active=true;

// User 的 ID 是 `111`
db.Model(&user).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;

// 根据条件和 model 的值进行更新
db.Model(&user).Where("active = ?", true).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true;

Update方法也可以更新多列数据,它支持structmap[string]interface{}参数。当使用struct更新时,默认情况下,GORM只会更新非零值的字段。如下所示:

// 根据 `struct` 更新属性,只会更新非零值的字段
db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})
// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;

// 根据 `map` 更新属性
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE users SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;

删除数据

使用Delete方法可以删除数据,删除一条记录时,删除对象需要指定主键(通过Where条件或者通过指针变量传入Delete方法),否则会触发批量Delete操作。下面是一些使用的例子:

// Email 的 ID 是 `10`
db.Delete(&email)
// DELETE from emails where id = 10;

// 带额外条件的删除
db.Where("name = ?", "jinzhu").Delete(&email)
// DELETE from emails where id = 10 AND name = "jinzhu";
db.Delete(&User{}, 10)
// DELETE FROM users WHERE id = 10;

db.Delete(&User{}, "10")
// DELETE FROM users WHERE id = 10;

db.Delete(&users, []int{1,2,3})
// DELETE FROM users WHERE id IN (1,2,3);