0

Spring / JPA / Hibernateアプリケーションを使用しており、H2およびMySQLに対するJunit統合テストに合格させようとしています。現在、トランザクションにはAtomikosを使用し、接続プールにはC3P0を使用しています。

私の最善の努力にもかかわらず、私のDAO統合は、テストの1つが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を持つ2番目のオブジェクトを作成して永続化することが原因であると確信していますが、各テストメソッドは独自のトランザクションであり、作成したオブジェクトはプライベートテストメソッド変数にバインドされています。ログでは、SpringTestと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>
4

2 に答える 2

1

これは変です。JPA仕様から:

3.3.2トランザクションのロールバック

トランザクションスコープと拡張永続コンテキストの両方で、トランザクションのロールバックによりすべて の既存のコンテキストが発生します管理対象インスタンスと削除されたインスタンスが切り離されます。インスタンスの状態は、トランザクションがロールバックされた時点でのインスタンスの状態になります。トランザクションのロールバックにより、通常、ロールバックの時点で永続コンテキストが一貫性のない状態になります。特に、バージョン属性の状態と生成された状態(たとえば、生成された主キー)は一貫していない可能性があります。したがって、以前は永続コンテキストによって管理されていたインスタンス(そのトランザクションで永続化された新しいインスタンスを含む)は、他の分離オブジェクトと同じ方法で再利用できない場合があります。たとえば、マージ操作に渡されたときに失敗する場合があります。

上記のセクションの読み方は、トランザクションがロールバックされると、JPAはその永続コンテキストをクリアする必要があるということです。

于 2010-06-14T12:51:55.790 に答える
1

この場合の問題は、アプリケーション管理の拡張トランザクションエンティティマネージャーがDAOに注入されていることでした。この理由はここで見つけることができます:

SpringコンテキストでJPAEntityManangerを作成する際の問題

エンティティマネージャーを修正すると、すべてが機能しました。

于 2010-06-15T18:53:23.630 に答える