gorm的find和first

查询 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.

first

first用于从数据库中检索单个对象

1
2
3
4
5
6
7
8
9
10
// 获取第一条记录(主键升序)
db.First(&user)
// SELECT * FROM users ORDER BY id LIMIT 1;

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

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

当查询数据库时它添加了 LIMIT 1 条件,且没有找到记录时,它会返回 ErrRecordNotFound 错误,因此一般业务中我们可以通过ErrRecordNotFound == nil来判断表中是否存在某条记录。如:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 根据userId(主键)查询user
var user User;
if err := db.First(&user, userId).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
// 不存在
// do something
} else {
// 其他err,数据库查询异常
// do something
}
}
// 存在 此时user即为查询结果
// do something

和first类似的方法:

1
2
3
4
5
6
7
// 获取一条记录,没有指定排序字段
db.Take(&user)
// SELECT * FROM users LIMIT 1;

// 获取最后一条记录(主键降序)
db.Last(&user)
// SELECT * FROM users ORDER BY id DESC LIMIT 1;

find

find用于从数据库中检索全部对象,可搭配where等方法条件检索部分对象

1
2
3
4
5
6
// Get all records
var users []User;
result := db.Find(&users)
// SELECT * FROM users;
result.RowsAffected // 返回找到的记录数,等价于 len(users)
result.Error // returns error

first和find

使用first时我们可以通过ErrRecordNotFound == nil来判断表中是否存在某条记录。如果你觉得通过错误来进行业务处理不够优雅,或者说如果你想避免ErrRecordNotFound错误,你可以使用Find,比如db.Limit(1).Find(&user),然后通过result.RowsAffected == 0来判断是否存在某条记录。如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 根据userId(主键)查询user
var user User;
if result := db.Where("user_id = ?", userId).Find(&user); result.Erroe != nil {
if result.RowsAffected == 0 {
// 不存在
// do something
} else {
// 存在
// do something
}
}else {
// err,数据库查询异常
// do something
}

这是因为find会直接返回查询结果,无论结果是什么,而first必须返回一条记录。

注意,对单个对象使用Find而不带limit,db.Find(&user)将会查询整个表并且只返回第一个对象,这是性能不高并且不确定的。