注解@Transactional。如何回滚?

问题描述 投票:0回答:5

我在 Dao 类中成功使用了这个注释。回滚适用于测试。

但现在我需要回滚真正的代码,而不仅仅是测试。 有一些特殊的注释可以在测试中使用。但是哪些注释适用于非测试代码呢? 这对我来说是一个大问题。我已经为此花费了一天的时间。官方文档并不能满足我的需求。

class MyClass { // this does not make rollback! And record appears in DB.
        EmployeeDaoInterface employeeDao;

        public MyClass() {
            ApplicationContext context = new ClassPathXmlApplicationContext(
                    new String[] { "HibernateDaoBeans.xml" });
            employeeDao = (IEmployeeDao) context.getBean("employeeDao");
         }

        @Transactional(rollbackFor={Exception.class})
    public void doInsert( Employee newEmp ) throws Exception {
        employeeDao.insertEmployee(newEmp);
        throw new RuntimeException();
    }
}

employeeDao 是

@Transactional
public class EmployeeDao implements IEmployeeDao {
    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public void insertEmployee(Employee emp) {
        sessionFactory.getCurrentSession().save(emp);
    }
}

这是一个注释效果很好的测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/HibernateDaoBeans.xml" })
@TransactionConfiguration(transactionManager = "txManager", defaultRollback = true)
@Transactional
public class EmployeeDaoTest {

    @Autowired
    EmployeeDaoInterface empDao;

    @Test
    public void insert_record() {
       ...
       assertTrue(empDao.insertEmployee(newEmp));
    }

HibernateDaoBeans.xml

   ...
<bean id="employeeDao" class="Hibernate.EmployeeDao">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
    <tx:annotation-driven transaction-manager="txManager"/>

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



**是的,我回滚了交易。我刚刚为服务添加了 BEAN...然后注释 @Transactional 开始工作:-) **

<bean id="service" class="main.MyClass">
    <property name="employeeDao" ref="employeeDao" />
</bean>

谢谢大家,俄罗斯不会忘记你们!

java hibernate spring
5个回答
191
投票

只需从标记为

RuntimeException
的方法中抛出任何
@Transactional

默认情况下,所有

RuntimeException
都会回滚事务,而受检查的异常则不会。这是 EJB 的遗产。您可以使用
rollbackFor()
noRollbackFor()
注释参数进行配置:

@Transactional(rollbackFor=Exception.class)

这将在抛出any异常后回滚事务。


118
投票

或以编程方式

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

5
投票

您可以从要回滚的方法中抛出未经检查的异常。这将被 spring 检测到,并且您的事务将被标记为仅回滚。

我假设您在这里使用 Spring。我假设您在测试中引用的注释是基于 Spring 测试的注释。

向 Spring 框架的事务基础结构指示事务工作要回滚的推荐方法是从当前在事务上下文中执行的代码中抛出异常。

并注意:

请注意,Spring 框架的事务基础结构代码默认情况下只会在运行时、未检查异常的情况下将事务标记为回滚;也就是说,当抛出的异常是 RuntimeException 的实例或子类时。


2
投票

对我来说 rollbackFor 还不够,所以我必须把它放在上面,它会按预期工作:

@Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)

我希望它有帮助:-)


0
投票

根据spring框架文档:

在其默认配置中,Spring 框架的事务基础设施代码仅在运行时、未检查的异常情况下标记回滚事务。

因此,为了将事务标记为回滚,请确保抛出 unchecked 运行时异常。

© www.soinside.com 2019 - 2024. All rights reserved.