golang db事务的统一封装的实现

目录
  • 简单封装
    • 偷懒第一步
    • 偷懒第二步
    • 偷懒第三步
  • 进一步封装

事务处理的流程示例

    database := db.DB
    tx, err := database.Begin()
    if err != nil {
        return err
    }
    stmt, err := tx.Prepare(sqlQuery)
    if err != nil {
        tx.Rollback()
        return err
    }
    _, err = stmt.Exec(paras...)
    if err != nil {
        tx.Rollback()
        return err
    }
    err = tx.Commit()
    if err != nil {
        tx.Rollback()
        return err
    }

以上是我们使用事务时的一般操作,如果每做一次事务的操作均要进行重新写一遍代码岂不是很麻烦,尤其是出错时,Rollback需要多次在不同错误的地方的进行调用处理。

简单封装

偷懒第一步

采用defer处理Rollback

defer tx.Rollback()

无论成功与否,均进行Rollback操作,只是有点影响,如果成功还调用Rollback的话,将会报错。虽然可以忽略,但作为程序员,有必要进一步调整。

偷懒第二步

根据执行结果来选择执行Rollback,避免无效使用。

defer func() { //根据执行结果选择执行Rollback
        if err != nil && tx != nil {
        log.Println("ExecSqlWithTransaction defer err :", err)
            tx.Rollback()
        }
    }()

如此,我们就可以根据事务的执行结果决定是否Rollback了。

偷懒第三步

封装,以上代码本身就具有极大的普适性,因此,我们抽出通用的参数,将此过程封装成一个func,以后就可以直接调用了。

func ExecSqlWithTransaction(database *sql.DB, query string, args ...interface{}) (err error) {
    tx, err := database.Begin()
    if err != nil {
        return err
    }
    defer func() {
        if err != nil && tx != nil {
            tx.Rollback()
        }
    }()
    stmt, err := tx.Prepare(query)
    if err != nil {
        return err
    }
    defer stmt.Close()
    _, err = stmt.Exec(args...)
    if err != nil {
        return err
    }
    return tx.Commit()
}

封装后我们可以如下使用:

if err := ExecSqlWithTransaction(database,sqlQuery,paras...);err != nil{
    //错误处理
}

封装后是不是很简洁啊?

进一步封装

在一个事务中可能会出现多个SELECT、UPDATE等操作,以上封装仅处理了一种操作,还不能满足我们的实际需求,因此需要更进一步封装。

func ExecSqlWithTransaction(db *sql.DB, handle func(tx *sql.Tx) error) (err error) {
 tx, err := db.Begin()
 if err != nil {
  return err
 }
 defer func() {
  if err != nil {
   tx.Rollback()
  }
 }()
 if err = handle(tx); err != nil {
  return err
 }
 return tx.Commit()
}

在handle func内可以直接使用事务tx进行增删改查。

到此这篇关于golang db事务的统一封装的实现的文章就介绍到这了,更多相关golang db事务封装内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • mongodb官方的golang驱动基础使用教程分享

    前言 mongo数据库在nodejs平台有2个常用驱动,mongodb和mongoose,mongodb接口非常接近mongo数据库原生的操作方式,是helloworld之类演示代码的首选mongo数据库连接驱动,因此成为大部分nodejs初学者最先接触的mongo数据库驱动.初学者在学会mongo连接的同时,却也可悲的被helloword这种演示性质的数据库操作习惯潜移默化了. 本文主要介绍的是关于mongodb官方的golang驱动使用的相关内容,下面话不多说了,来一起看看详细的介绍吧 使用

  • golang配制高性能sql.DB的使用

    目录 开放和空闲连接 SetMaxOpenConns方法 SetMaxIdleConns方法 SetConnMaxLifetime方法 连接数量超出 总结 有很多教程是关于Go的sql.DB类型和如何使用它来执行SQL数据库查询的.但大多数内容都没有讲述SetMaxOpenConns(), SetMaxIdleConns() 和 SetConnMaxLifetime()方法, 您可以使用它们来配置sql.DB的行为并改变其性能. 在本文我将详细解释这些设置的作用,并说明它们所能产生的(积极和消极

  • Golang对MongoDB数据库的操作简单封装教程

    前言 Golang 对MongoDB的操作简单封装 使用MongoDB的Go驱动库 mgo,对MongoDB的操作做一下简单封装 mgo(音mango)是MongoDB的Go语言驱动,它用基于Go语法的简单API实现了丰富的特性,并经过良好测试. 初始化 操作没有用户权限的MongoDB var globalS *mgo.Session func init() { s, err := mgo.Dial(dialInfo) if err != nil { log.Fatalf("Create Se

  • golang 连接mongoDB的方法示例

    Mogondb 不支持事务.所有有事务要求的需求慎用,比如银行的转账操作慎用,转1个亿美金,因为网络,电力的故障导致交易没有完成,不能回滚,交易无法撤回.所有慎用!! Mogondb 的应用场景: 比如一篇CSDN博客,博客内容,博客作者,发布时间,评论,阅读量等信息可以将这些信息存储到一个类似JSON数据中.如果用mysql需要将不同的信息分别存储于不同的表中,使用的时候,查询多表或者使用JOIN查询数据,导致查询过慢.而使用MongoDB,将数据存储在一起,需要数据时,一次就能查询到数据.更

  • Golang Mongodb模糊查询的使用示例

    前言 在日常使用的Mongodb中,有一项功能叫做模糊查询(使用正则匹配),例如: db.article.find({"title": {$regex: /a/, $options: "im"}}) 这是我们常用Mongodb的命令行使用的方式,但是在mgo中做出类似的方式视乎是行不通的: query := bson.M{"title": bson.M{"$regex": "/a/", "$opt

  • golang db事务的统一封装的实现

    目录 简单封装 偷懒第一步 偷懒第二步 偷懒第三步 进一步封装 事务处理的流程示例 database := db.DB tx, err := database.Begin() if err != nil { return err } stmt, err := tx.Prepare(sqlQuery) if err != nil { tx.Rollback() return err } _, err = stmt.Exec(paras...) if err != nil { tx.Rollback

  • Laravel统一封装接口返回状态实例讲解

    前后端分离,接口返回封装方便你我他(方便前后端合作开发) 在Laravel中可以在公共继承的Controller.php写方法进行调用返回 app/Http/Controllers/Controller.php 成功返回 /** * $msg 返回提示消息 * $data 返回数据 */ public function success($msg,$data = []) { return response()->json([ 'status' => true, 'code' => 200,

  • SpringBoot实现统一封装返回前端结果集的示例代码

    在实际项目开发过程中.事实上我们经常用@restcontroller注释的方式,将相当于将返回数据的基本形式统一为JSON格式的数据.但是,由于我们的项目可能是由很多人开发的,所以我们最好将返回的结果统一起来,这样每个人都可以返回相同的数据格式,这不仅规范了代码,也方便了前端人员调用,否则每个人都会按照自己的风格编写,代码会变得非常混乱. 我们如何封装这个结果?我们应该注意返回到前端的数据中包含的信息. 一般来说,首先,这次必须有一个code来表示接口的状态.例如,0表示成功,1表示失败,2表示

  • golang如何优雅的编写事务代码示例

    前言 新手程序员大概有如下特点 if嵌套经常超过3层.经常出现重复代码.单个函数代码特别长. 只会crud,对语言特性和语言的边界不了解. 不懂面向对象原则和设计模式,以为copy代码就算学会了,常见的是代码职责不明确或者写出万能类 不知道数据结构和算法的重要性,以为靠硬件能解决运行慢的问题 架构不懂,搭建框架不会,搭建环境不会,使用的软件底层原理一问三不知 其实吧,很多人干了很多年,看似是老手,平时工作看似很忙,其实做的都是最简单的活. 这就像去锻炼,有的人每天练的很积极,准时打卡,频繁发朋友

  • axios封装,使用拦截器统一处理接口,超详细的教程(推荐)

    最近从0开始搭了一个vue-cli的项目, 虽然axios也可以直接拿来用,但是对接口比较零散,不太好进行维护,也会产生大量的重复代码,所以笔者对axios进行了统一接口处理,废话不多说,直接上代码. 首先,在vue-cli项目的src路径下新建一个axios文件夹,在axios文件夹里新建aps.js和request.js,api.js用于写接口,对axios的封装写在request.js里,项目机构如图: 1. axios统一封装 然后开始统一封装axios, 首先引入axios.qs依赖,

  • spring事务Propagation及其实现原理详解

    本文研究的主要是spring事务Propagation及其实现原理,具体介绍如下. 简介 spring目前已是java开发的一个事实标准,这得益于它的便利.功能齐全.容易上手等特性.在开发过程当中,操作DB是非常常见的操作,而涉及到db,就会涉及到事务.事务在平时的开发过程当中,就算没有注意到,程序正常执行不会有副作用,但如果出现了异常,而又没有处理好事务的话,可能就会出现意想不到的结果.spring在事务方面进行了各种操作的封装,特别是声明式事务的出现,让开发变得更加的舒心.spring对事务

  • 详解SQL Server中的事务与锁问题

    一  概述 在数据库方面,对于非DBA的程序员来说,事务与锁是一大难点,针对该难点,本篇文章试图采用图文的方式来与大家一起探讨. "浅谈SQL Server 事务与锁"这个专题共分两篇,上篇主讲事务及事务一致性问题,并简略的提及一下锁的种类和锁的控制级别. 下篇主讲SQL Server中的锁机制,锁控制级别和死锁的若干问题. 二   事务 1   何为事务 预览众多书籍,对于事务的定义,不同文献不同作者对其虽有细微差别却大致统一,我们将其抽象概括为: 事务:指封装且执行单个或多个操作的

  • Java中JDBC事务与JTA分布式事务总结与区别

    Java事务的类型有三种:JDBC事务.JTA(Java Transaction API)事务.容器事务.常见的容器事务如Spring事务,容器事务主要是J2EE应用服务器提供的,容器事务大多是基于JTA完成,这是一个基于JNDI的,相当复杂的API实现.所以本文暂不讨论容器事务.本文主要介绍J2EE开发中两个比较基本的事务:JDBC事务和JTA事务. JDBC事务 JDBC的一切行为包括事务是基于一个Connection的,在JDBC中是通过Connection对象进行事务管理.在JDBC中,

  • 详解SpringBoot的事务管理

    Springboot内部提供的事务管理器是根据autoconfigure来进行决定的. 比如当使用jpa的时候,也就是pom中加入了spring-boot-starter-data-jpa这个starter之后. Springboot会构造一个JpaTransactionManager这个事务管理器. 而当我们使用spring-boot-starter-jdbc的时候,构造的事务管理器则是DataSourceTransactionManager. 这2个事务管理器都实现了spring中提供的Pl

  • Jersey框架的统一异常处理机制分析

    一.背景 写这边文章源于有朋友问过java中的checked exception和unchecked exception有啥区别,当时我对其的回答是:我编程时仅用RuntimeException.其实,我说句话我是有前提的,确切的应该这么说:在成熟的开发框架下编写业务代码,我只使用或关注RuntimeException.因为,由于框架往往将异常的处理统一封装,这样以便程序员更好的关注业务代码,而业务的一些错误通常是在系统运行期间发生的,因此业务的异常通常被设计为RuntimeException的

随机推荐