随笔 - 100  文章 - 50  trackbacks - 0
<2014年12月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

常用链接

留言簿(3)

随笔分类

随笔档案

文章分类

文章档案

收藏夹

我收藏的一些文章!

搜索

  •  

最新评论

阅读排行榜

评论排行榜

框架采用的是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>

 

 

    经测试,此问题暂时得到解决,不知道会不会引起其它问题,至少目前还没有发现其它异常。您若通过此方案解决之后出现了新的问题请留信回复,我们一起交流,非常感谢!

 

posted on 2014-12-20 14:23 fly 阅读(584) 评论(0)  编辑  收藏 所属分类: J2EE

只有注册用户登录后才能发表评论。


网站导航: