Atomikos回滚不清楚JPA持久化上下文?

时间:2010-06-14 05:08:47

标签: hibernate jpa jta c3p0 autocommit

我有一个Spring / JPA / Hibernate应用程序,我试图让它通过针对H2和MySQL的Junit集成测试。目前我使用Atomikos进行交易,使用C3P0进行连接池。

尽管我付出了最大努力,但我的DAO集成其中一个测试失败了org.hibernate.NonUniqueObjectException。在失败的测试中,我使用“new”运算符创建一个对象,设置ID并在其上调用persist。

@Test
@Transactional
public void save_UserTestDataNewObject_RecordSetOneLarger() {
    int expectedNumberRecords = 4;
    User newUser = createNewUser();

    dao.persist(newUser);   
    List<User> allUsers = dao.findAll(0, 1000);

    assertEquals(expectedNumberRecords, allUsers.size());
}

在之前的测试方法中,我做了同样的事情(createNewUser()是一个帮助器方法,每次都创建一个具有相同ID的对象)。我确信创建和持久化具有相同Id的第二个对象是原因,但每个测试方法都在自己的事务中,并且我创建的对象绑定到私有测试方法变量。我甚至可以在日志中看到Spring Test和Atomikos正在回滚与每种测试方法相关的事务。

我原以为回滚也会清除持久化上下文。在预感中,我在错误的测试方法开始时添加了对dao.clear()的调用,问题就消失了!所以回滚不清除持久化上下文???如果没有,那么谁呢?

我的EntityManagerFactory配置如下:

<bean id="myappTestLocalEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="myapp-core" />
        <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="true" />
                <property name="database" value="$DS{hibernate.database}" />
                <property name="databasePlatform" value="$DS{hibernate.dialect}" />
            </bean>
        </property>

        <property name="jpaProperties">
            <props>
                <prop key="hibernate.transaction.factory_class">com.atomikos.icatch.jta.hibernate3.AtomikosJTATransactionFactory</prop>
                <prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop>
                <prop key="hibernate.connection.autocommit">false</prop>
                <prop key="hibernate.format_sql">true"</prop>
                <prop key="hibernate.use_sql_comments">true</prop>
    </property>
</bean>

2 个答案:

答案 0 :(得分:1)

这很奇怪。从JPA规范:

  

3.3.2交易回滚

     

对于事务范围和   扩展持久化上下文,   事务回滚导致所有   预先存在的托管实例和已删除的实例将被分离。   实例的状态将是州   在这一点上的实例   该交易已回滚。   事务回滚通常会导致   持久化上下文   在这一点上的不一致状态   回滚。特别是,状态   版本属性和生成的状态   (例如,生成的主键)可以是   不一致。那些实例   以前由持久性管理   上下文(包括新的实例)   坚持不懈   因此,交易)可能不是   可以像其他方式一样重复使用   分离的对象 - 例如,他们可能   传递给合并时失败   操作

我阅读上述部分的方式是,当回滚事务时,JPA应该清除其持久化上下文。

答案 1 :(得分:1)

在这种情况下的问题最终是我有一个应用程序管理,扩展事务实体管理器注入我的DAO。原因可以在这里找到:

Problem creating JPA EntityMananger in Spring Context

一旦我修复了我的实体经理 - 一切正常。