Spring集成测试不会回滚

时间:2011-10-01 07:38:03

标签: hibernate spring integration-testing dao rollback

我正在使用Spring + Hibernate + H2。我在集成测试中进行数据库操作(通过调用服务类)。我希望Spring在每个测试方法之后回滚更改,但我无法让它工作。起初我使用MySQL(使用MyISAM,它不支持事务),但在更改为H2之后问题仍然存在。我尝试了几个DataSource定义(在阅读之后它必须是XA感知的),但似乎没有任何帮助。

我在我的服务层使用http://code.google.com/p/generic-dao/作为DAO-classes和@Transactional-annotations(如果删除它们,我会收到以下错误:javax.persistence.TransactionRequiredException:没有正在进行的事务)。< / p>

我的测试类看起来像这样:

@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());
}
}

这是我的弹簧配置:

<!-- <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"> -->
<!-- <property name="driverClassName" value="org.h2.Driver" /> -->
<!-- <property name="url" value="jdbc:h2:~/test" /> -->
<!-- <property name="username" value="sa" /> -->
<!-- <property name="password" value="" /> -->
<!-- </bean> -->
<!--    <bean id="myDataSource" class=" com.mchange.v2.c3p0.ComboPooledDataSource"> -->
<!--        <property name="driverClass" value="org.h2.Driver" /> -->
<!--        <property name="jdbcUrl" value="jdbc:h2:~/test" /> -->
<!--        <property name="user" value="sa" /> -->
<!--        <property name="password" value="" /> -->
<!--    </bean> -->

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

这是我的服务实施:

@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));
    }
}

编辑:dao.persist() - 方法基本上封装了对来自genericdao的以下方法的调用(em返回当前的EntityManager):

/**
 * <p>
 * Make a transient instance persistent and add it to the datastore. This
 * operation cascades to associated instances if the association is mapped
 * with cascade="persist". Throws an error if the entity already exists.
 * 
 * <p>
 * Does not guarantee that the object will be assigned an identifier
 * immediately. With <code>persist</code> a datastore-generated id may not
 * be pulled until flush time.
 */
protected void _persist(Object... entities) {
    for (Object entity : entities) {
        if (entity != null)
            em().persist(entity);
    }
}

一切正常,但更改仍保留在数据库中。有什么想法吗?

1 个答案:

答案 0 :(得分:7)

我认为您需要从AbstractTransactionalTestNGSpringContextTests而不是AbstractTestNGSpringContextTests进行扩展。