只有在子方法中发生异常时才进行事务回滚 [英] No rollback only for transaction when exception occurs in submethod

查看:1574
本文介绍了只有在子方法中发生异常时才进行事务回滚的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Hibernate + spring + @Transactional 注解来处理我的应用程序中的事务。

事务经理声明如下:

 < bean id =transactionManagerclass =org.springframework.orm.hibernate3.HibernateTransactionManager > 
< property name =sessionFactoryref =sessionFactory/>
< / bean>

< tx:注解驱动的事务管理器=transactionManager/>

这在大多数情况下效果很好,但我发现一个问题,我有两种方法,两种注释@Transactional:

  package temp; 

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

public class OuterTestService {
@Autowired
private InnerTestService innerTestService;

@Transactional
public void outerMethod(){
try {
innerTestService.innerTestMethod();
} catch(RuntimeException e){
//这里的一些代码
}
}
}

  package temp; 

import org.springframework.transaction.annotation.Transactional;

public class InnerTestService {

@Transactional
public void innerTestMethod()抛出RuntimeException {
throw new RuntimeException();


当我调用OuterTestService#outerMethod()时,一个异常

  org.springframework.transaction.UnexpectedRollbackException:事务回滚,因为它已被标记为仅回退
由于只有一个事务(没有嵌套事务),整个 outerTestMethod()

code>的交易被标记为仅回滚。



我发现我可以使用noRollbackFor轻松解决这个问题:

  package cz.csas.pdb.be.service.tempdelete; 

import org.springframework.transaction.annotation.Transactional;

public class InnerTestService {

@Transactional(noRollbackFor = RuntimeException.class)
public void innerTestMethod()抛出RuntimeException {
throw new RuntimeException() ;
}
}

但是这必须在每种方法中明确使用。因为这个错误在测试期间没有被提出(这是回滚的),所以这是不可接受的。



我的问题 - 有没有办法自动(例如,每个方法)设置只有在启动事务的方法引发异常时才会回滚事务(在这种情况下, outerTestMethod())?

解决方案

创建另一个注释,例如 @NoRollbackTransactional ,类似于:

  @Transactional(noRollbackFor = RuntimeException。类)
public @interface NoRollbackTransactional {
}

然后在你的方法。另一方面,我同意Donal的评论,你应该修改你的交易范围,从另一个调用 @Transactional 通常不是一个好主意。 @Transactional

I'm using Hibernate + spring + @Transactional annotations to handle transactions in my application.

Transaction manager is declared as follows:

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>

This works well in most cases, but I've found a problem where I have 2 methods, both annotated @Transactional:

package temp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

public class OuterTestService {
    @Autowired
    private InnerTestService innerTestService;

    @Transactional
    public void outerMethod() {
        try {
            innerTestService.innerTestMethod();
        } catch (RuntimeException e) {
            // some code here
        }
    }
}

and

package temp;

import org.springframework.transaction.annotation.Transactional;

public class InnerTestService {

    @Transactional
    public void innerTestMethod() throws RuntimeException {
        throw new RuntimeException();
    }
}

When I invoke OuterTestService#outerMethod(), I get an exception

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

As there is only one transaction (no nested transactions), the whole outerTestMethod()'s transaction is marked as rollback-only.

I've found that I can easily overcome this using noRollbackFor:

package cz.csas.pdb.be.service.tempdelete;

import org.springframework.transaction.annotation.Transactional;

public class InnerTestService {

    @Transactional(noRollbackFor = RuntimeException.class)
    public void innerTestMethod() throws RuntimeException {
        throw new RuntimeException();
    }
}

But this has to be explicitly used on every method. Because this error is not raised during tests (which are rollbacked), this is not acceptable.

My question -- is there a way to automatically (eg. not explicitly for every method) set that transactions are rolled back only when an exception is raised from method which started the transaction (in this case, the outerTestMethod())?

解决方案

Create another annotation, e.g. @NoRollbackTransactional, something like:

@Transactional(noRollbackFor = RuntimeException.class)
public @interface NoRollbackTransactional {
}

And use this on your methods. On the other hand I agree with Donal's comment, you should revise your transaction scopes, imho it is generally not a good idea to call @Transactional from another @Transactional.

这篇关于只有在子方法中发生异常时才进行事务回滚的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆