框架采用的是spring管理声明式事务

 框架采用的是spring管理声明式事务,这几天业务开发时遇到了点麻烦,记录下备忘。

 

 场景:在Service类中使用子事务(saveponit)时,当子事务抛出异常后,此异常处理掉不继续往外抛,spring在提交主事务时会抛出

org.springframework.transaction.UnexpectedRollbackException: Transaction has been rolled back because it has been marked as rollback

 

 方法调用结构:

      假若有A、B、C三个Service类,其实例对象分别为a、b、c,类分别定义如下:

 

            A {

                    方法() {                   //propagation="REQUIRED"

  try{

 

                                b.方法();

   } catch (Exception e) {

           }

                    }      

   }

 

            B{

                     savePoint方法() {  //propagation="NESTED"

   c.方法(); //如果这里边的操作全是普通类(不是Service类)操作,不会有问题。

                     }

             }

 

 

            C{

                      方法() {                 //propagation="REQUIRED"

  throw new Exception("出错");

     }

 

              }

 

 

   通过调试spring源码 

           ......

           Getting transaction for [A.方法] .....

           ......

   Creating nested transaction with name [B.savePoint方法]........

   ......

           Participating in existing transaction

           Getting transaction for [C.方法]

           ........

   Participating transaction failed - marking existing transaction as rollback-only

           //此时,已把主事务标记成了rollback-only

 

           所以,当在a.方法完成时提交事务时会报Transaction has been rolled back because it has been marked as rollback错误。

 

           认真的您可能会发现,在 org.springframework.transaction.support.AbstractPlatformTransactionManager 中有个叫

isGlobalRollbackOnParticipationFailure的参数,默认是true.

 

          源码中说明:

 

        Switch this to "false" to let the transaction originator make the rollback decision. If a participating transaction fails with an exception, the caller can still decide to continue with a different path within the transaction. However, note that this will only work as long as all participating resources are capable of continuing towards a transaction commit even after a data access failure: This is generally not the case for a Hibernate Session, for example; neither is it for a sequence of JDBC insert/update/delete operations.

 

          大意是:如果isGlobalRollbackOnParticipationFailure为false,则会让主事务决定回滚,如果当遇到exception加入事务失败时,调用者能继续在事务内决定是回滚还是继续。然而,要注意是那样做仅仅适用于在数据访问失败的情况下且只要所有操作事务能提交。

 

        

    初步解决方案:

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> <property name="globalRollbackOnParticipationFailure" value="false" /> <!--指定此参数为false-->

</bean>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值