java 配置嵌套事务_Spring嵌套事务解惑(重点)

PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。

PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。

PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED -- 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

前六个策略类似于EJB CMT,第七个(PROPAGATION_NESTED)是Spring所提供的一个特殊变量。

它要求事务管理器或者使用JDBC 3.0 Savepoint API提供嵌套事务行为(如Spring的DataSourceTransactionManager

PROPAGATION_REQUIRES_NEW 启动一个新的, 不依赖于环境的 "内部" 事务. 这个事务将被完全 commited 或 rolled back 而不依赖于外部事务, 它拥有自己的隔离范围, 自己的锁, 等等. 当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行.

另一方面, PROPAGATION_NESTED 开始一个 "嵌套的" 事务,  它是已经存在事务的一个真正的子事务. 潜套事务开始执行时,  它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交.

PROPAGATION_REQUIRES_NEW 启动一个新的, 不依赖于环境的 "内部" 事务. 这个事务将被完全 commited 或 rolled back 而不依赖于外部事务, 它拥有自己的隔离范围, 自己的锁, 等等. 当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行.

另一方面, PROPAGATION_NESTED 开始一个 "嵌套的" 事务,  它是已经存在事务的一个真正的子事务. 潜套事务开始执行时,  它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交.

由此可见, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于, PROPAGATION_REQUIRES_NEW 完全是一个新的事务, 而 PROPAGATION_NESTED 则是外部事务的子事务, 如果外部事务 commit, 潜套事务也会被 commit, 这个规则同样适用于 roll back.

由此可见,

PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于,

PROPAGATION_REQUIRES_NEW 完全是一个新的事务, 而

PROPAGATION_NESTED 则是外部事务的子事务, 如果外部事务 commit, 潜套事务也会被 commit,

这个规则同样适用于 roll back.

当然, 就算所有嵌套事务都已经成功, 外部事务还是可能因为嵌套事务的执行结果而导致失败,  此时整个事务都要 roll back ,这也是嵌套事务的重要特性之一, 即外部事务和嵌套事务互相影响

只有需要根据子事务的执行情况进行分支处理的情况下才是nested的用武之地, savepoint是嵌套事务回滚的实现方式 需要注意的是使用它的限制条件

使用嵌套事务是有前提的,就是该嵌套事务可能需要做分支处理。否则用PROPAGATION_REQUIRED 就足够了,如果子事务有异常,直接回滚。

nested 可以在外层rollback所有内层的事务。requiresnew 不行。

例子:

ServiceA {

/**

* 事务属性配置为 PROPAGATION_REQUIRED

*/

void methodA() {

ServiceB.methodB();

}

}

ServiceB {

/**

* 事务属性配置为 PROPAGATION_REQUIRES_NEW

*/

void methodB() {

}

}

PROPAGATION_REQUIRES_NEW 时 ServiceB.methodB 没办法回滚到它执行之前的 SavePoint, 这时已经产生了一些脏数据, 而这些脏数据将可能导致后面的程序执行出错

ServiceA {

/**

* 事务属性配置为 PROPAGATION_REQUIRED

*/

void methodA() {

try{

ServiceB.methodB();

}catch(Exeception e){

ServiceC.methodC();

}

}

}

ServiceB {

/**

* 事务属性配置为 PROPAGATION_NESTED

*/

void methodB() {

}

}

对于PROPAGATION_NESTED的嵌套事务而言,如果ServiceB.methodB()异常,会会回滚到上一个savepoint点,外层事务A,可以捕获,处理ServiceC.methodC(),但是对于ServiceA.methodA()异常,会回滚整个嵌套的事务

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值