在我的 Spring 2.5.6 + Hibernate 应用程序中,我需要从具有不同模式的多个数据库读取/写入数据。该应用程序位于 Tomcat 上,因此我暂时不想使用 JTA,这样我就不需要迁移到成熟的应用程序服务器。
所以我决定只有一个事务数据源。我可以和其他人一起生活,而不是交易。
但不知何故,我无法让它工作。你能看看我可能做错了什么吗?
这是我的 applicationContext.xml:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- ..configuration.. -->
</bean>
<bean id="nonTransactionalSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="nonTransactionalDataSource" />
<!-- ..configuration.. -->
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!-- ..configuration.. -->
</bean>
<bean id="nonTransactionalDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<!-- ..configuration.. -->
</bean>
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="daoHolder" class="com.app.services.TransactionTest$DaoHolder"/>
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="transactionalDao" class="com.app.services.TransactionalDaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="nonTransactionalDao" class="com.app.services.NonTransactionalDaoImpl">
<property name="sessionFactory" ref="nonTransactionalSessionFactory" />
</bean>
如您所见,上面只是两个会话工厂的定义,每个都使用自己的数据源。事务管理器仅使用这些会话工厂之一,并且配置了注释驱动的 tx-management。
这是我试图测试事务行为的单元测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/applicationContext.xml"})
public class TransactionTest {
@Autowired
private DaoHolder daoHolder;
@Test
public void testTransactions() throws Exception {
try {
daoHolder.runTransactionalMethod();
} catch (Exception exception) {
System.out.println("Exception caught");
}
}
public static class DaoHolder {
@Autowired
private TransactionalDao transactionalDao;
@Autowired
private NonTransactionalDao nonTransactionalDao;
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW, rollbackFor={Exception.class})
private void runTransactionalMethod() throws Exception {
transactionalDao.insertRow();
nonTransactionalDao.insertRow();
throw new Exception();
}
}
作为上述测试的结果,我希望将新行插入到非事务数据源中,因为事务数据源上的更改应该回滚,因为抛出了异常。但是,在此测试通过后,我看到两个数据源中都插入了行。
编辑:我已经走得更远了。我已经将 DaoHolder 变成了一个接口,将上述逻辑移到了一个实现接口的类(DaoHolderImpl)中,并用@Transactional 标记了这个类(不仅仅是方法)。我还将此类添加为 Spring Bean。所以现在 Spring 处理我的事务。但是这一次,当抛出异常时,新行会从两个数据源中回滚,而不仅仅是事务性的。这仍然不是我所期望的:/
有谁看到我做错了什么?提前致谢,
彼得