Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Spring+;DBUnit+;朱尼特_Spring_Junit_Dbunit_Spring Transactions - Fatal编程技术网

如何使用Spring+;DBUnit+;朱尼特

如何使用Spring+;DBUnit+;朱尼特,spring,junit,dbunit,spring-transactions,Spring,Junit,Dbunit,Spring Transactions,简而言之 我的命令行Java应用程序将数据从一个数据源复制到另一个数据源,而不使用XA。我已经配置了两个独立的数据源,并且想要一个JUnit测试,它可以回滚两个数据源上的数据。我使用DBUnit将数据加载到“源”数据库中,但无法使其回滚。我可以让“目标”数据源回滚 我的代码 给定此配置 <tx:annotation-driven /> <!-- note the default transactionManager name on this one --> <be

简而言之

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

我的代码

给定此配置

<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>
在我看来,问题在于
@TransactionConfiguration
仅说明用于启用回滚的目标数据源。DBUnit正在显式传递
dataSourceA
,并正在获取名为
transactionManager
(我不确定如何)的默认事务管理器,该事务管理器未被告知回滚

问题

如何告诉两个事务管理器回滚

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

注意:应用程序在生产中运行时不需要dataSourceA上的事务管理器,因为它只会是只读的。此问题仅适用于我的测试类。

在事务管理器定义中使用
元素

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSourceA" />
    <qualifier value="transactionManager" />
</bean>

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

我使用开源TM Atomikos在JUnit测试中使用了XA事务和回滚。一个很好的特性是Atomikos允许使用未启用XA的数据源参与XA事务。查看此链接以获取示例:


另一方面,如果XA是解决JUnit问题的合适解决方案,那就另当别论了。您的测试主要关注数据库实现(Sybase)还是更多地关注Java逻辑?我通常为JUnit测试设置嵌入式数据库,如ApacheDerby或HQSQL。那么我就不必太在意清理了,因为GC会处理:)

一个可能的解决方法是引入一个注释为
@Transactional(“transactionManagerTarget”)
的助手bean,并将您的测试注释为
@Transactional(“transactionManager”)
,使用
defaultRollback=true
配置两者。然后,您的测试必须调用helperbean,而helperbean又将调用您的测试服务bean。这将导致围绕服务的事务回滚,然后围绕DBUnit的事务回滚

不过有点乱

其他可能的办法:

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

我对这不起作用的理解是,
@Before
@Test
方法将在同一事务中执行,我无法指定多个@Transactional注释。在您的回答中,我看不出它是如何告诉
transactionManager
回滚的。我错过什么了吗?不过,使用
很好。我在我的测试类上尝试了
@Transactional
的各种用法,但不幸的是,我怀疑
@test
方法启动了一个事务,而
@Before
无法为DBUnit启动另一个事务,因此它继续与transactionManagerTarget一起运行,因此不会回滚DBUnit数据。我想我尝试了所有我能使用的注释,但没有运气。谢谢你的回复。DBUnit仅用于加载测试数据,因为该数据源已经由另一个服务在生产中填充。因此,我在生产中没有XA问题,因为我只向一个目标数据源写入数据。我喜欢您将HSQL用于我的“源”数据源的想法。我只需要弄清楚如何存储我的模式以供HSQL加载,并使其与Sybase模式保持一致。任何JTA TM对我都没有好处,因为我的两个数据源都不是XA。大多数JTA TM允许您使用一个非XA数据源,但不允许使用很长的时间,但是。。跳过HQSQL,对其中一个数据源(源)使用ApacheDerby。不能将架构存储在test/resources/source\u db\u setup.sql中吗?Derby已启用XA。然后可以使用sybase作为非xa源。我认为应该有一些其他的选择给你,虽然,我现在没有什么好主意。我试着分解出一个helperbean,但这并没有帮助我们进行转换。当有多个TransactionManager时,后台数据库单元不会回滚。我将接受您的答案,使用HSQL作为前进的方向,但是在我的例子中,我仍然被卡住了,因为我使用Sybase在这个数据源上创建了一个临时表,并且语法与HSQL不兼容。
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSourceA" />
    <qualifier value="transactionManager" />
</bean>

<bean id="transactionManagerTarget" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSourceB" />
    <qualifier value="transactionManagerTarget" />
</bean>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:resources/spring-context.xml",
                                "classpath:resources/spring-db.xml"})  
@Transactional("transactionManagerTarget")
@TransactionConfiguration(defaultRollback = true) 
public class MyIntegrationTest {
...