当前位置: 首页 > 面试题库 >

当子方法中发生异常时,仅事务不会回滚

韦泳
2023-03-14
问题内容

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

事务管理器声明如下:

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

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

在大多数情况下,此方法效果很好,但是我发现一个问题,我有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
        }
    }
}

package temp;

import org.springframework.transaction.annotation.Transactional;

public class InnerTestService {

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

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

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

由于只有一个事务(没有嵌套事务),因此整个outerTestMethod()事务都标记为“仅回滚”。

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

但这必须在每种方法上明确使用。因为在测试(回滚)过程中不会引发此错误,所以这是不可接受的。

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


问题答案:

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

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

并在您的方法上使用它。另一方面,我同意Donal的评论,您应该修改您的交易范围,恕我直言,@Transactional与他人通话通常不是一个好主意@Transactional



 类似资料:
  • 问题内容: 我在下面使用HIbernate和Spring和JPA。当引发PersistenceException时,我想捕获它并返回错误消息,以便它不会传播到调用者。 但是我得到一个异常,说我需要在异常之后回滚事务,但是当我捕获到异常并且不想重新抛出该异常时,如何回滚它呢? 问题答案: 似乎没有办法回退由Spring ORM管理的失败事务。问题中显示的代码是服务类。将其持久性例程提取到单独的DAO

  • 我有一个RESTFul服务(由泽西实施)。服务用@Transactional标记。 我声明了一个ExceptionMapper,如下所示: 未声明exceptionmapper时,事务将回滚。然而,当我有一个ExceptionMapper时,事务是提交而不回滚。 我假设事务未回滚的原因是,当异常被ExceptionMapper捕获时,spring事务代理dosnt检测到异常被抛出,因此事务未回滚。

  • 问题内容: 为了了解Spring事务的工作原理,我想知道在以下情况下会发生什么情况,其中一种方法标记为,而另一种方法标记为。 假设配置使用所有默认设置。 现在,如果我要输入,显然可以开始交易。然后,钻进去会发生什么?事务已经存在的事实会导致没有新的事务诞生,还是我在这里创建两个事务? 关于传播的文档(在下面引用)似乎涵盖了这一点,但是我想验证一下我的理解,这对于我的处女大脑来说可以一次理解所有知识

  • 问题是即使抛出了未检查的异常,methodC()也不会回滚。

  • 这很好,但并不总是在代码中抛出运行时异常。因此,我挖掘并发现如下所示的rollbackFor; 现在,我必须更改所有代码,以使用RollBackfor更改@Transactional。但是还有其他方法可以将所有@transaction advice属性更改为rollbackFor=exception.class吗?

  • 问题内容: 为了了解Spring事务的工作原理,我想知道在以下情况下发生的情况:如果一种方法标记为,而另一种方法标记为。 假设配置使用所有默认设置。 现在,如果我要输入,显然可以开始交易。然后,钻进去会发生什么?交易已经存在的事实会导致没有新的交易诞生,还是我在这里创建两个交易? 关于Propagation的文档(在下面引用)似乎涵盖了这一点,但是我想验证一下我的理解 Propagation:通常