您的位置:首页 > 编程语言 > Java开发

脱离 Spring 实现复杂嵌套事务,之二(REQUIRED - 加入已有事务)

2016-04-07 19:16 483 查看

PROPAGATION_REQUIRED(加入已有事务)

定义:

尝试加入已经存在的事务中,如果没有则开启一个新的事务。

解释:

解释 REQUIRED 行为并不困难。它是指如果当前连接中如果已经开启了数据库事务,并且有程序在控制这个事务。那么在处理 REQUIRED 行为时将会忽略 commit/rollback 操作,这是加入已有事务的特征。

时间事务1事务2
T1开始事务
T2操作1...
T3加入事务1
T4操作2...
T5操作3...
T6递交事务
定义中有一句“如果没有则开启一个新的事务”这句话怎么理解?

所谓“没有”指的是当前连接中不存在事务(事务状态为false)。“则开启新的事务”这里的可以理解为,如果没有事务那么才开启新的事务。而且新开启的事务是需要事务管理器进行维护的。

工作原理





开启事务

事务管理器在创建 REQUIRED 类型事务时,会取得当前连接这一过程会持有当前连接(引用计数+1)。

然后通过判断当前连接是否存在事务状态,来决定是否通过 doBegin 方法开启事务。这个规则为:如果存在事务状态则忽略,否则开启。

一般情况下在调用 doBegin 方法之前事务都是尚未开启的。我们知道没有开启事务的连接特征是 autoCommit 属性为 true。在这种情况下每一次SQL操作都是独立成为一个事务,因此多条SQL语句之间是不存在事务关系的。换句话说只要进入 doBegin 方法的数据库连接都是没有开启事务的连接,它们都满足 new 状态的特征

事务中的数据库操作

无论在开启事务的时候Connection 此时此刻,可以直接使用 Connection 接口畅快的使用数据库操作。由于每次进行数据库操作都要反复的申请和释放数据库连接。这会反复的使引用计数 +1,-1。

递交/回滚事务

REQUIRED 行为告诉我们,如果环境中有事务控制,那么该行为下的事务管理器将不作为。所有事务控制操作交给环境中的事务控制来处理。

但是如果环境中不存在事务,那么事务管理器是需要负责 commit & rollback 的。

这时候在前面确定的 new 状态就可以发挥作用了。因为根据 new 状态的特征描述我们知道凡是持有 new 状态的数据库连接在开启事务之前是不存在先前事务的。作为后来者的事务管理器而言,可以放心大胆的去递交事务。

如果不具备 new 特征则正好说明外部在事务管理器之外有其它程序代码代为控制了事务。

例如下面这个业务逻辑(伪代码):

?
在上面这个例子中,第四行中开启了事务。因此在执行 insertData 的时候事务管理器会认为当前连接中已经存在事务,新的事务只需要加入到当前的事务中即可。并不需要独立控制事务。因此在最后 insertData 方法结束的时,其插入的数据还未真正的插入到数据库。随后外部事务控制代码又将所有数据都回滚了。

上面的代码修改一下如下:

?
上面的代码中我们可以看出,insertData 方法之外的程序并没有控制事务。 insertData 中的事务管理器在创建事务对象的时候,由于当前连接满足 new 状态特征。所以在最后 tm.commit(status) 时会执行事务递交操作。

而上面第8行,所使用的连接由于也没有开启事务。所以它会以自动递交事务的方式去运行。

关于 afterClear

afterClear 阶段的作用是将当前连接的状态恢复到 getTransaction 方法之前。并且由于 getTransaction 方法会持有当前连接(引用计数++),因此 afterClear 方法也会释放掉这个连接的持有(引用计数--)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: