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

问题描述:

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

My DAO integration tests are failing because entities created during the tests are still in the database at the start of the next test. The exact same behavior is seen from both MySQL 5 and H2.

测试类带有以下注释:

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

测试应用程序上下文中的事务Bean配置如下:

The transaction bean configuration in the test application context is as follows:

<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>

实体管理器的配置如下:

The entity manager is configured as follows:

<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="$DS{hibernate.database}" />
            <property name="databasePlatform" value="$DS{hibernate.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的有关回滚的消息.但坦率地说,原木是如此之大,如此复杂,以至于我很容易会遗漏某些东西...

Everything in the log files seem to be fine...I can see messages from Spring about rollback and from Atomikos about rollback as well. But frankly, the logs are so huge and so complex, I could easily be missing something...

但是插入的测试数据仍然保留!有什么线索吗?

Yet the inserted test data remains! Any clues?

事实证明,我的C3P0 JDBC数据源不支持XA,因此未参与事务.我不知道为什么我没有在日志文件中得到错误或警告.尽管如此,很好地在此处解释了无法使用XA感知数据源的原因.请注意,数据源不需要具有XA功能...只需了解XA.

It turned out that my C3P0 JDBC data source was not XA aware and was therefore not participating in the transaction. Why I did not get an error, nor a warning in the log file, I do not know. Nonetheless, the reason you cannot use an XA aware data source is explained very nicely here. Note that the data source does not need to be XA capable...just XA aware.

用以下一种替换C3P0数据源解决了这个问题.

Replacing the C3P0 data source with the following one solved the problem.

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