spring 子方法发生异常时只对事务不回滚

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6097012/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 04:30:30  来源:igfitidea点击:

No rollback only for transaction when exception occurs in submethod

hibernatespringtransactionsrollback

提问by Ondrej Skalicka

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

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

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:

这在大多数情况下都很有效,但我发现了一个问题,我有 2 个方法,都注释了 @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

当我调用 OuterTestService#outerMethod() 时,出现异常

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.

由于只有一个事务(没有嵌套事务),整个outerTestMethod()事务被标记为仅回滚。

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

我发现我可以使用 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())?

我的问题 - 有没有一种方法可以自动(例如,不是针对每个方法明确地)设置事务仅在启动事务的方法(在本例中为outerTestMethod())引发异常时才回滚?

回答by abalogh

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

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

@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 @Transactionalfrom another @Transactional.

并在您的方法中使用它。另一方面,我同意 Donal 的评论,您应该修改您的交易范围,恕我直言,@Transactional从另一个@Transactional.

回答by jasop

You may also need to turn off globalRollbackOnParticipationFailure.

您可能还需要关闭globalRollbackOnParticipationFailure

I had this problem when I had an independent transaction within a surrounding transaction. When the independent transaction failed, it also failed the surrounding transaction.

当我在周围交易中进行独立交易时,我遇到了这个问题。当独立事务失败时,它也使周围事务失败。

Turning off the participation flag solved this for me:

关闭参与标志为我解决了这个问题:

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