I am using Spring + Hibernate + H2. I perform database operations in my integration tests (by calling a service class). I want Spring to roll back the changes after each testing method, but I cannot get it to work. At first I used MySQL (with MyISAM, which does not support the transaction), but after changing to H2 the problem remains. I tried several DataSource definitions (after reading that this should be XA-aware) but nothing helps.
I use http://code.google.com/p/generic-dao/ for my DAO classes and @ Transactional annotations at my service level (if I delete them, I get the following error: javax.persistence.TransactionRequiredException: transaction not executed).
My test classes are as follows:
@ContextConfiguration("classpath:...spring.xml") @Transactional @TransactionConfiguration(transactionManager="transactionManager", defaultRollback=true) public class DemoServiceTest extends AbstractTestNGSpringContextTests{ @Autowired private DemoService demoService; @Test public void addTest() { int size = demoService.findAll().size(); Test coach = new Test(); test.setName("Test"); testService.save(test); Assert.assertEquals(size+1,testService.findAll().size()); } }
Here is my spring configuration:
<bean id="myDataSource" class="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean"> <property name="uniqueResourceName" value="test" /> <property name="driverClassName" value="org.h2.Driver" /> <property name="url" value="jdbc:h2:~/test" /> <property name="user" value="sa" /> <property name="password" value="" /> <property name="maxPoolSize" value="20" /> <property name="reapTimeout" value="300" /> </bean> <bean id="demoDAO" class="...DemoDAOImpl" /> <bean id="demoService" class="...DemoServiceImpl" /> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="test" /> <property name="persistenceXmlLocation" value="classpath:persistence.xml" /> <property name="dataSource" ref="myDataSource" /> <property name="loadTimeWeaver"> <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" /> </property> <property name="jpaVendorAdapter" ref="vendorAdapter" /> </bean> <bean id="vendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="database" value="H2" /> <property name="showSql" value="true" /> <property name="generateDdl" value="true" /> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <bean id="searchProcessor" class="com.googlecode.genericdao.search.jpa.JPASearchProcessor"> <constructor-arg ref="metadataUtil" /> </bean> <bean id="metadataUtil" class="com.googlecode.genericdao.search.jpa.hibernate.HibernateMetadataUtil" factory-method="getInstanceForEntityManagerFactory"> <constructor-arg ref="entityManagerFactory" /> </bean> <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> <tx:annotation-driven />
And what is my service implementation:
@Transactional public class TestServiceImpl implements TestService { private TestDAO<Test,Long> dao; @Autowired public void setDao(TestDAO<Test,Long> dao) { this.dao = dao; } public void save(Test test) { dao.persist(test); dao.flush(); } public List<Test> findAll() { return dao.findAll(); } public Test findByName(String name) { if (name == null) return null; return dao.searchUnique(new Search().addFilterEqual("name", name)); } }
EDIT: The dao.persist () method basically encapsulates a call to the following method from genericdao (em returns the current EntityManager):
protected void _persist(Object... entities) { for (Object entity : entities) { if (entity != null) em().persist(entity); } }
Everything works fine, but the changes remain in the database. Any ideas?