记一次gorm.ErrRecordNotFound踩坑记录

【踩坑日记】记一次gorm.ErrRecordNotFound踩坑记录

在某个项目中,有个数据验证的业务,即在数据库中查询数据是否存在,若数据已存在则返回错误并给前端提示。稍想了一下就能写出如下代码Func01

Func01

1
2
3
4
5
6
7
8
func (t *ServiceInfo) Find(c *gin.Context, tx *gorm.DB, search *ServiceInfo) (*ServiceInfo, error) {
	out := &ServiceInfo{}
	err := tx.WithContext(c).Where(search).Find(out).Error
	if err != nil {
		return nil, err
	}
	return out, nil
}

gorm在之前的版本中,因为gorm的查询是链式的语句,所以中间出现的错误会存入到Error的参数集中处理。而且当没有查询到数据的时候也会得到错误ErrRecordNotFound。所以此代码就把错误同一处理,当controller中没有收到任何错误时,可以说明数据库中查询到了此数据,即校验重复了。

但是经过测试后发现无论如何err都是nil,且RowsAffected也明明为0。在网上也没有直接搜到这个坑的blog,于是我去翻了gorm最新的文档,发现了此段话!

image-20220725104008262

即说明Find()方法不会再得到ErrRecordNotFound的错误

于是我采用了First()进行了测试

Func02

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
func (t *ServiceInfo) Find(c *gin.Context, tx *gorm.DB, search *ServiceInfo) (*ServiceInfo, error) {
	out := &ServiceInfo{}
	resultFind := tx.WithContext(c).Where(search).Find(out)
	resultFirst := tx.WithContext(c).Where(search).First(out)
	log.Print("Find() Err: ", resultFind.Error, "\tFind Rows Affected: ", resultFind.RowsAffected)
	log.Print("First() Err: ", resultFirst.Error, "\tFind Rows Affected: ", resultFirst.RowsAffected)
	err := resultFind.Error
	if err != nil {
		return nil, err
	}
	return out, nil
}

得到输出

1
2
2022/07/25 10:00:35 Find() Err: <nil>   Find Rows Affected: 0
2022/07/25 10:00:35 First() Err: record not found       Find Rows Affected: 0

很明显,当查询不到结果的时候First()方法会返回ErrRecordNotFound,而Find()方法并不会

因此,若不改变代码原有的逻辑基础上,可以通过手动添加Error的方法来完成数据校验的工作

Func03

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
func (t *ServiceInfo) Find(c *gin.Context, tx *gorm.DB, search *ServiceInfo) (*ServiceInfo, error) {
	out := &ServiceInfo{}
	resultFind := tx.WithContext(c).Where(search).Find(out)
	if resultFind.RowsAffected < 1 {
		err := resultFind.AddError(gorm.ErrRecordNotFound)
		if err != nil {
			return nil, err
		}
	}
	err := resultFind.Error
	if err != nil {
		return nil, err
	}
	return out, nil
}

即通过resultFind.RowsAffected < 1来判断是否查询到数据,再通过 resultFind.AddError(gorm.ErrRecordNotFound) 手动添加

ErrRecordNotFound错误,藉此来完成在旧版本中存在的功能。

PS:我个人并不是很理解为什么要取消Find()方法中的这个错误提示

​ 此实现方式仅供参考,如有更漂亮的方法希望不吝赐教

Built with Hugo
主题 StackJimmy 设计