注释@Transactional 如何回滚?

我成功地将这个注释用于 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();
}
}

杜员工

@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));
}

HibernateDougBeans.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>

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

172134 次浏览

Just throw any RuntimeException from a method marked as @Transactional.

By default all RuntimeExceptions rollback transaction whereas checked exceptions don't. This is an EJB legacy. You can configure this by using rollbackFor() and noRollbackFor() annotation parameters:

@Transactional(rollbackFor=Exception.class)

This will rollback transaction after throwing any exception.

You can throw an unchecked exception from the method which you wish to roll back. This will be detected by spring and your transaction will be marked as rollback only.

I'm assuming you're using Spring here. And I assume the annotations you refer to in your tests are the spring test based annotations.

The recommended way to indicate to the Spring Framework's transaction infrastructure that a transaction's work is to be rolled back is to throw an Exception from code that is currently executing in the context of a transaction.

and note that:

please note that the Spring Framework's transaction infrastructure code will, by default, only mark a transaction for rollback in the case of runtime, unchecked exceptions; that is, when the thrown exception is an instance or subclass of RuntimeException.

or programatically

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

For me rollbackFor was not enough, so I had to put this and it works as expected:

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

I hope it helps :-)