Go 数据库操作异常处理

877 阅读2分钟

这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战

Go 数据库操作异常处理

插入操作

第一种写法

err := db.Model(&XXX{}).Create(order).Error
	if err != nil {
		logs.CtxError(ctx, "Create XXX failed, err:%v", err.Error())
		return  err
	}

第二种写法

db := db.Model(&XXX{}).Create(order)
	if db.Error != nil {
		logs.CtxError(ctx, "Create XXX failed, err:%v", db.Error)
		return  db.Error
	}

上述两种写法说明:

两种写法都没啥问题,第一种写法, 如果只插入一条数据,可以使用第一种写法简单;第二种写法可以拿到执行的 *DB ,方便后续的 DB 操作

更新操作

db := db.Model(&Voucher{}).Where(whereMap).Updates(updateMap)
if db == nil {
	return 0, errors.New(fmt.Sprintf("UpdateVoucherWithState failed, db is null, jrUid:%s, voucherNo:%s", jrUid, voucherNo))
}
err := db.Error

if err != nil {
	logs.CtxError(ctx, "UpdateXXX failed err:%v", err)
}
if db.RowsAffected != 1{
 logs.CtxWarn(ctx, "UpdateXXX failed RowsAffected:%v", db.RowsAffected)
// TODO 根据业务自身特性单独处理
}

说明:

update 方法将返回执行完之后的 *DB, 需要通过指针对象才能获取正确的 RowAffected

事务处理

tx, txErr = model.BeginTransactionNotShard(ctx)
	if txErr != nil {
		logs.CtxError(ctx, "db BeginTransaction err: %v", txErr)
		return constant.GenRetCode(constant.DBError, txErr.Error())
	}
	defer func() {
		if err := recover(); err != nil {
			logs.CtxError(ctx, "panic:%+v", err)
			tx.Rollback(ctx, tx)
		} else if  err != nil {
			// logs.CtxError
			tx.Rollback()
		}
	}()

	if err := tx.Error; err != nil {
		return err
	}
	if err:= tx.Create(&XXX).Error; err != nil {
    	 return err 
    }
	return tx.Commit().Error

事务的提交也可能会有 error, 要判断是否正确 commit

需要判断 tx.Error,因为事务的提交可能会有 error

查询的异常处理

if err := db.Where("name = ?", "jianzhu").First(&user).Error; err != nil {
	if errors.Is(err, gorm.ErrRecordFound) {
			// TODO 业务处理查询不到数据的情况
	} 
	if  err != nil {
	 		// do something  ...
	}
}

其实要注意的是,没查询到结果,也会返回一个Error

gormErrRecordNotFound也好理解,假设根据身份证号查询公民信息,如果是一个无效的身份证ID,那必然无法查询到结果, 其实就是查询不到结果,会返回一个错误。

当然 GORM 提供了一个处理 RecordNotFound 错误的快捷方式,如果发生了多个错误,它将检查每个错误,如果它们中的任何一个是RecordNotFound 错误。

//检查是否返回 RecordNotFound 错误
db.Where("name = ?", "hello world").First(&user).RecordNotFound()

if db.Model(&user).Related(&credit_card).RecordNotFound() {
  // 数据没有找到
}

if err := db.Where("name = ?", "jinzhu").First(&user).Error; gorm.IsRecordNotFoundError(err) {
  // 数据没有找到
}
欢迎关注工作号:程序员财富自由之路

参考资料