Тест интеграции Spring/JTA/JPA DAO не откатывается?
Мои интеграционные тесты DAO не проходят, потому что объекты, созданные во время тестов, все еще находятся в базе данных в начале следующего теста. Точно такое же поведение видно из MySQL 5 и H2.
Тестовые классы снабжены пометкой:
@Transactional
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration( { "/testPersist-applicationContext.xml" })
Конфигурация компонента транзакции в контексте тестового приложения выглядит следующим образом:
<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="$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 об откате. Но, честно говоря, журналы настолько огромны и сложны, что я мог бы что-то упустить...
Тем не менее, вставленные данные теста остаются! Есть какие-нибудь подсказки?
2 ответа
Оказалось, что мой источник данных C3P0 JDBC не был осведомлен о XA и поэтому не участвовал в транзакции. Почему я не получил ни ошибки, ни предупреждения в лог-файле, я не знаю. Тем не менее, причина, по которой вы не можете использовать источник данных с поддержкой XA, очень хорошо объясняется здесь. Обратите внимание, что источник данных не обязательно должен поддерживать XA... только XA-осведомленный.
Замена источника данных C3P0 на следующий решил проблему.
<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>
Я думаю, вам нужно будет детально просмотреть журналы. Может случиться так, что откаты, которые вы видите, работают, за исключением того, что кто-то еще выполнил коммит первым. Я также не вижу ничего в вашем коде, что указывает на автоматический откат. И это должно происходить в конце каждого теста. Если вы используете откат на основе тайм-аута, возможно, второй тест выполняется до истечения тайм-аута, поэтому он видит данные до его отката.
Много вариантов тут есть:-)