Spring + Hibernate:一起使用事务和非事务数据源

时间:2011-12-28 13:10:37

标签: hibernate spring transactional

在我的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处理我的交易。但是这一次,当抛出异常时,新行将从两个数据源回滚,而不仅仅是事务性数据源。这仍然不是我所期待的:/

有谁看到我做错了什么? 提前谢谢,

彼得

1 个答案:

答案 0 :(得分:1)

如何将断点放在“抛出异常”行,以便您可以查看一个或两个数据库是否具有该行?

它不会修复您的奇怪回滚而不会出现问题,但可能会告诉您非事务性数据源是否运行良好。

您宁愿启用spring / hibernate日志记录来查看有关事务的信息......