【问题标题】:Rollback error in using Spring DBUnit, Spring Data and embedded H2 database使用 Spring DBUnit、Spring Data 和嵌入式 H2 数据库时出现回滚错误
【发布时间】:2014-05-11 07:41:05
【问题描述】:

我遇到了一个古玩错误。

我有一个小的 DBUnit 测试:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("classpath:spring/testApplicationContext.xml") 
@Category(Integrationtest.class)
@TestExecutionListeners({ 
    DependencyInjectionTestExecutionListener.class,
    DirtiesContextTestExecutionListener.class,
    TransactionDbUnitTestExecutionListener.class
    })
@DatabaseSetup("classpath:db/wbSchluesselwertData.xml")
public class KontaktrolleRepositoryIntegrationTest {


    @Autowired
    KontaktrolleRepository kontaktrolleRepository;

    @Autowired
    KontaktBeteiligterRepository kontaktBeteiligterRepository;

    @Autowired
    WbSchluesselwertRepository wbSchluesselwertRepository;
........
........
    @Test
    @Transactional
    public void that_Kontaktrolle_Is_Inserted_Into_DB() throws Exception {

        WbSchluesselwert wbRolle1 = wbSchluesselwertRepository.findOne(new Long(11)); 

        KontaktBeteiligter b1 = new KontaktBeteiligterBuilderAws(erzeugtAm).withName("Posteingang")
                .withStandort("Cologne").withOrganization("private").build();


        KontaktBeteiligter result = kontaktBeteiligterRepository.save(b1);

        Kontaktrolle r1 = new KontaktrolleBuilder(erzeugtAm).withBeteiligter(result).withRollenartId(wbRolle1).build();

        Kontaktrolle resultRolle = kontaktrolleRepository.save(r1);

        assertNotNull(resultRolle);
        assertNotNull(resultRolle.getKontaktrolleId());
        assertThat(resultRolle.getKontaktrolleId(), greaterThan(0L));

    }

仅此而已。首先,我想搜索一个由 DBUnit (wbSchluesselwertData.xml) 预填充的条目。 之后,我想通过 Spring Data CrudRepository 在嵌入式 H2 内存数据库中保存两个条目。

此数据源由 HibernateJpaVendorAdapter 和适配器本身包装在 LocalContainerEntityManagerFactoryBean 中:

<bean id="emf"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
    <property name="packagesToScan" value="de.axa.chronik.persistence.domain" />
</bean>

如果我运行上面的单元测试,我会收到以下错误:

21:21:55,808 DEBUG JpaTransactionManager:594 - Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@f6b9e9] after transaction
21:21:55,808 DEBUG EntityManagerFactoryUtils:338 - Closing JPA EntityManager
21:21:55,809  WARN TestContextManager:397 - Caught exception while allowing TestExecutionListener [com.github.springtestdbunit.TransactionDbUnitTestExecutionListener@4c4b3e] to process 'after' execution for test: method [public void de.axa.chronik.persistence.repository.KontaktrolleRepositoryIntegrationTest.that_Kontaktrolle_Is_Inserted_Into_DB() throws java.lang.Exception], instance [de.axa.chronik.persistence.repository.KontaktrolleRepositoryIntegrationTest@be41d5], exception [null]
org.springframework.transaction.TransactionSystemException: Could not roll back JPA transaction; nested exception is javax.persistence.PersistenceException: unexpected error when rollbacking
    at org.springframework.orm.jpa.JpaTransactionManager.doRollback(JpaTransactionManager.java:544)...............
...........
Caused by: org.hibernate.TransactionException: unable to rollback against JDBC connection
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doRollback(JdbcTransaction.java:167)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.rollback(AbstractTransactionImpl.java:209)
    ... 33 more
Caused by: org.h2.jdbc.JdbcSQLException: Das Objekt wurde bereits geschlossen
The object is already closed [90007-175]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:332)

因此,由于连接已关闭,后续保持实体的尝试失败。 hibernate persist 和我忽略的使用 ob Spring DBUnit 之间是否存在现有影响?

感谢任何帮助。 非常感谢。

问候, 博多

【问题讨论】:

  • 我在使用 H2、Spring 和 Hibernate (JPA) 的 DbUnit 测试中收到相同的错误消息 JdbcSQLException: The object is already closed [90007-195]。所以我想这个问题与 Spring Data 无关。
  • 如果我将TransactionDbUnitTestExecutionListener.class 更改为DbUnitTestExecutionListener.class,错误就会消失,但数据库更改不会在测试后回滚。

标签: spring spring-data h2 sqlexception spring-test-dbunit


【解决方案1】:

当您手动配置测试执行侦听器时,您需要注册TransactionalTestExecutionListener,否则事务不会在测试级别启动。当存储库返回您所看到的原因异常时,这将导致事务已经关闭。

【讨论】:

  • 嗯,很遗憾,我根本没有让你回答。
  • 很遗憾,我根本没有给你答复。在我的 applicationContext 中,我使用属性 LocalContainerEntityManagerFactoryBean 设置了 JpaTransactionManager。在上面的 testCase 中,我注册了 TransactionDbUnitTestExecutionListener.class。代替这个类,我可以注册 TransactionalTestExecutionListener.class 和 DbUnitTestExecutionListener.class,但效果相同。我也可以用 Rollback(false) 注释测试方法,但这也没有任何效果。我的内存数据库在我的 testApplicationContext 中声明:..
  • TransactionDbUnitTestExecutionListener.class 更改为 TransactionalTestExecutionListener.class + DbUnitTestExecutionListener.class 有助于消除此错误。我现在可以确认我的测试是在事务中执行的。 BUT 在事务结束时(即在每个测试用例之后),@DatabaseSetup 中所做的更改不会回滚。
  • 这玩意让我陷入精神不稳定的状态……只有注册DbUnitTestExecutionListener之前TransactionalTestExecutionListener才有效。
【解决方案2】:

尝试更改您的TestExecutionListeners。这个设置对我有用:

@TestExecutionListeners({
    DependencyInjectionTestExecutionListener.class,
    DbUnitTestExecutionListener.class,
    TransactionalTestExecutionListener.class
})

不再有org.h2.jdbc.JdbcSQLException: The object is already closed [90007-175] 错误,我的测试现在在事务中执行。 在 DbUnit 的 @DatabaseSetup 中所做的更改不会在事务结束时回滚(即在每个测试用例之后)。

【讨论】:

    猜你喜欢
    • 2012-10-22
    • 2018-06-13
    • 1970-01-01
    • 2013-03-14
    • 2014-02-03
    • 2015-10-07
    • 2017-03-01
    • 2013-08-11
    • 2013-02-03
    相关资源
    最近更新 更多