注释@Transactional。如何回滚?

时间:2011-10-24 08:08:44

标签: java hibernate spring

我成功地为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>

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

4 个答案:

答案 0 :(得分:122)

从标有RuntimeException的方法中抛出任何@Transactional

默认情况下,所有RuntimeException回滚事务,而已检查的异常则不会。这是EJB的遗产。您可以使用rollbackFor()noRollbackFor()注释参数进行配置:

@Transactional(rollbackFor=Exception.class)

这会在抛出任何异常后回滚交易。

答案 1 :(得分:54)

或以编程方式

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

答案 2 :(得分:4)

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

我假设你在这里使用Spring。我假设你在测试中提到的注释是基于弹簧测试的注释。

  

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

并注意:

  

请注意,默认情况下,Spring Framework的事务基础结构代码仅在运行时未经检查的异常情况下标记事务以进行回滚;也就是说,抛出的异常是RuntimeException的实例或子类。

答案 3 :(得分:-1)

对我来说rollbackFor还不够,所以我不得不放这个,它按预期工作:

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

我希望它有所帮助: - )