Spring/JTA/JPA DAO 集成测试不回滚?

Posted

技术标签:

【中文标题】Spring/JTA/JPA DAO 集成测试不回滚?【英文标题】:Spring/JTA/JPA DAO integration test doesn't rollback? 【发布时间】:2011-03-08 20:56:14 【问题描述】:

我的 DAO 集成测试失败,因为在测试期间创建的实体在下一次测试开始时仍在数据库中。从 mysql 5 和 H2 可以看到完全相同的行为。

测试类注释为:

@Transactional
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(  "/testPersist-applicationContext.xml" )

测试应用上下文中的事务bean配置如下:

<tx:annotation-driven />

<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="atomikosTransactionManager" />
    <property name="userTransaction" ref="atomikosUserTransaction" />
</bean>

<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
    <property name="forceShutdown" value="false" />
</bean>

<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
    <property name="transactionTimeout" value="300" />
</bean>

实体管理器配置如下:

<bean id="myappTestLocalEmf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="myapp" />
    <property name="persistenceUnitPostProcessors">
        <bean                class="com.myapp.core.persist.util.JtaPersistenceUnitPostProcessor">
        <property name="jtaDataSource" ref="myappPersistTestJdbcDataSource" />
        </bean>
    </property>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="false" />
            <property name="database" value="$DShibernate.database" />
            <property name="databasePlatform" value="$DShibernate.dialect" />
        </bean>
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup
            </prop>
            <prop key="hibernate.format_sql">true"</prop>
            <prop key="hibernate.use_sql_comments">true</prop>
            </props>
    </property>
</bean>

<context:annotation-config />

日志文件中的所有内容似乎都很好...我可以看到来自 Spring 的有关回滚的消息以及来自 Atomikos 的有关回滚的消息。但坦率地说,日志是如此庞大和复杂,我很容易遗漏一些东西......

但插入的测试数据仍然存在!有什么线索吗?

【问题讨论】:

【参考方案1】:

事实证明,我的 C3P0 JDBC 数据源不支持 XA,因此没有参与事务。为什么我没有收到错误,也没有在日志文件中出现警告,我不知道。尽管如此,here 很好地解释了您不能使用 XA 感知数据源的原因。请注意,数据源不需要支持 XA...只需支持 XA。​​

将 C3P0 数据源替换为以下数据源即可解决问题。

<bean id="myappJTANonXADataSource" class="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean">
        <property name="uniqueResourceName" value="myappDatabase" />
        <property name="driverClassName" value="$DShibernate.connection.driver_class" />
        <property name="url" value="$DShibernate.connection.url" />
        <property name="user" value="$DShibernate.connection.username" />
        <property name="password" value="$DShibernate.connection.password" />
        <property name="maxPoolSize" value="20" />
        <property name="reapTimeout" value="300" />
</bean>

【讨论】:

非常感谢,遇到了类似的问题(没有 Spring),它帮助了我【参考方案2】:

我认为您需要详细查看日志。可能是您看到的回滚正在工作,除了其他东西首先执行了提交。我在您的代码中也看不到任何表明自动回滚的内容。并且它应该在每次测试结束时发生。如果您依赖于基于超时的回滚,则可能是第二个测试在超时发生之前正在运行,因此它会在回滚之前看到数据。

这里有很多选项:-)

【讨论】:

Spring 测试运行器执行回滚。我可以看到 Spring Test 和 Atomikos 创建事务并执行回滚。但是,Hibernate/JDBC 数据连接似乎不能正确同步。为了确保这不是 Spring Test、C3P0、JDBC 或 Hibernate 问题,我切换到 RESOURCE_LOCAL 持久性单元,数据源直接注入我的实体管理器,一切都按预期工作。所以问题在于 Atomikos 和/或我的后处理器解决方法,因为在应用服务器之外缺少 JNDI。

以上是关于Spring/JTA/JPA DAO 集成测试不回滚?的主要内容,如果未能解决你的问题,请参考以下文章

在集成测试中每个方法不回滚后 Spring Data JPA 数据库更改

使用JPA的Spring数据不会在出错时回滚事务

弹簧测试在测试后不回滚

如何不回滚以前的方法持久化数据?

一个简单的 Dao 集成测试不起作用

使用 Spring Test 自动回滚 DAO 集成测试是一种好习惯吗?