本文介绍了如何使用Spring + DBUnit + JUnit配置多个事务管理器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简而言之

我的命令行Java应用程序将数据从一个数据源复制到另一个数据源,而无需使用XA.我已经配置了两个单独的数据源,并且想要一个可以在两个数据源上回滚数据的JUnit测试.我使用DBUnit将数据加载到源"数据库中,但是无法将其回滚.我可以将目标"数据源回滚.

My command line Java application copies data from one datasource to another without using XA. I have configured two separate datasources and would like a JUnit test that can rollback data on both datasources. I use DBUnit to load data into the "source" database, but I cannot get this to rollback. I can get the "target" datasource to rollback.

我的代码

给出此配置...

<tx:annotation-driven />

<!-- note the default transactionManager name on this one -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource"     ref="dataSourceA" />
</bean>

<bean id="transactionManagerTarget" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource"     ref="dataSourceB" />
</bean>

和此代码...

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:resources/spring-context.xml",
                                "classpath:resources/spring-db.xml"})
@Transactional
@TransactionConfiguration(transactionManager = "transactionManagerTarget", defaultRollback = true)
public class MyIntegrationTest {

    @Autowired
    private MyService service;

    @Autowired
    @Qualifier("dataSourceA")
    private DataSource dataSourceA;

    private IDataSet loadedDataSet;

    /**
     * Required by DbUnit
     */
    @Before
    public void setUp() throws Exception {
        SybaseInsertIdentityOperation.TRUNCATE_TABLE.execute(getConnection(), getDataSet());
        SybaseInsertIdentityOperation.INSERT.execute(getConnection(), getDataSet());
    }

    /**
     * Required by DbUnit
     */
    protected IDataSet getDataSet() throws Exception {
        loadedDataSet = DbUnitHelper.getDataSetFromFile(getConnection(), "TestData.xml");
        return loadedDataSet;
    }

    /**
     * Required by DbUnit
     */
    protected IDatabaseConnection getConnection() throws Exception{
        return new DatabaseConnection(dataSourceA.getConnection());
    }

    @Test
    public void testSomething() {

        // service.doCopyStuff();

    }

}

我所看到的问题是,@TransactionConfiguration仅声明了用于启用回滚的目标数据源. DBUnit正在显式传递dataSourceA,并正在使用名为transactionManager的默认事务管理器(我不确定如何),该事务管理器尚未被告知要回滚.

The problem as I see it, is that @TransactionConfiguration only states the target datasource for enabling a rollback. DBUnit is being passed dataSourceA explicitly and is picking up the default transaction manager named transactionManager (I'm not sure how) which has not been told to rollback.

问题

我如何告诉两个交易经理回滚?

How can I tell both transaction managers to rollback?

当我的数据源不支持XA事务时,我可以使用一个事务管理器吗?

Can I use a single transaction manager when my datasources do not support XA transactions?

注意:在生产环境中运行时,该应用程序不需要dataSourceA上的事务管理器,因为它将是只读的.这个问题仅适用于我的测试班.

推荐答案

一个可行的解决方法是引入一个注释为@Transactional("transactionManagerTarget")的辅助bean,并使测试注释为@Transactional("transactionManager"),并同时使用defaultRollback = true进行配置.然后,您的测试将不得不调用助手bean,而后者又将调用您的被测试服务bean.这将导致服务周围的事务回滚,然后DBUnit周围的事务回滚.

A possible workaround would be to introduce a helper bean annotated as @Transactional("transactionManagerTarget") and leave your test annotated as @Transactional("transactionManager"), configuring both with defaultRollback = true. Your test would then have to call the helper bean, which in turn would call your service bean under test. This should cause the transaction around your service to roll back, then the transaction around DBUnit.

但是,这有点混乱.

其他可能的方法:

  • 使用内存数据库(例如H2)而不是生产数据库-您可以将其配置为在需要时删除其所有数据.
  • 允许DBUnit提交,并在您的拆卸方法中进行补偿事务以清除数据.

这篇关于如何使用Spring + DBUnit + JUnit配置多个事务管理器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 06:51
查看更多