1

取引内取引に関して疑問があります。背景として、Set of Students エンティティ オブジェクトがマップされた School エンティティ オブジェクトがあります。すべてのクラッド操作を処理するSpring Data JPAを使用しています。クラスレベルで @Transactional(readonly=true) が設定された SchoolManagementService クラスがあり、すべての更新メソッドに対して @Transactional を使用しています。私の SchoolManagementService クラスには、@Transactional としてマークしたメソッド deleteStudents(List) があります。このメソッドでは、StudentsRepository.delete(studentId) を何度も呼び出しています。削除が失敗した場合、トランザクションはそのチェックされた例外に対してロールバックする必要があることを確認したいと思います。

@RunWith(SpringJUnit4ClassRunner.class)   
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})   
@ContextConfiguration(locations = {"classpath:PPLRepository-context.xml"})
public class TestClass{


@Test
@Transactional
public void testDeleteStudents(){
StudentManagementService.delete(randomList)
}

このテストケースでは、最後のレコードを除くすべてのレコードを削除しています。理想的には、ロールバックし、どのエントリも削除しないようにする必要があります。

ここに、TransactionMangaer 構成を含む私の sprin 設定ファイルがあります

<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init"
            destroy-method="close">
            <property name="forceShutdown" value="true" />
            <property name="startupTransactionService" value="true" />
            <property name="transactionTimeout" value="1000" />
        </bean>

        <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" />
        <!-- Configure the Spring framework to use JTA transactions from Atomikos -->
        <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
            <property name="transactionManager" ref="atomikosTransactionManager" />
            <property name="userTransaction" ref="atomikosUserTransaction" />
            <property name="transactionSynchronizationName" value="SYNCHRONIZATION_ON_ACTUAL_TRANSACTION" />
        </bean>

            <!-- EntityManager Factory that brings together the persistence unit, datasource, and JPA Vendor -->
            <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="PPL_GMR">
                <property name="dataSource" ref="PPL_GMRDS"></property>
                <property name="persistenceUnitName" value="PPL_GMR"/>
                <property name="persistenceXmlLocation" value="classpath:META-INF/PPL-persistence.xml"/>
                <property name="jpaVendorAdapter" ref="PPL_GMRJPAVendorAdapter"/>
                    <property name="jpaPropertyMap">
                        <map>
                                    <entry key="hibernate.transaction.manager_lookup_class" value="com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup"/> 
                                    <entry key="hibernate.connection.release_mode" value="on_close"/>
                                    <entry key="hibernate.default_schema" value="${PPL.schema}"/>
                        </map>
                    </property>
</bean>

トランザクションに関する私の理解がどこで間違っているかを誰かが提案できますか? API から読み取ったものは何でも、あるメソッドがサービス層で @Transactional であり、Spring Data JPA リポジトリの複数の @Transactional メソッドを呼び出す場合、ランタイム例外が発生した場合、すべてのトランザクションをロールバックする必要があるという印象を受けました。 . 以下のようにテストケースメソッドを簡単に作成しようとしました:

@Test
@Transactional
public void testDeleteStudents(){
StudentRepository.delete(1);
StudentRepository.delete(2);// 2 id is not present so I will get a runtime exception.
}

このメソッドで @Rollback(true/false) を保持しているにもかかわらず、このメソッドは id 1 Student をデータベースから削除します。このテストケース メソッドの @Transactional は、ここで新しいトランザクションを作成し、StudentRepository からのすべてのトランザクション削除メソッドは同じトランザクションで実行されると考えました。また、ランタイム例外がスローされない限り、学生データはコミットされません。

私はこれが初めてなので、取引をよりよく理解するのを手伝ってください。Oracle データベースで Spring Data JPA を使用しています。

前もって感謝します。

4

1 に答える 1

0

デフォルトの動作は(テストクラスにないとしても)だと思います

@TransactionConfiguration(defaultRollback = true)

そのため、テストが終了するとロールバックが実行されます。したがって、データベースとの休止状態セッションの同期はなく、クエリ SQL はデータベースに発行されません。

2 つの可能性があります。どちらかを指定

@TransactionConfiguration(defaultRollback = false)

またはエンティティマネージャーをテストに挿入して呼び出します

@PersistenceContext
protected EntityManager em;

/**
 * Simulates new transaction (empties Entity Manager cache).
 */
public void simulateNewTransaction() {
    em.flush();
    em.clear();
}

これにより、休止状態がすべてのクエリをデータベースに送信するようになります。これにより、存在しないエンティティの削除に関する問題が解決されることに注意してください。ただし、新しいトランザクションとまったく同じように動作しないことに注意してください。たとえば、外部キーが見つからない場合、何もスローされません (これは予測可能です。

これを使用して、em.find(class, id) によって返されたエンティティの内容を確認し、トランザクションをコミットすることなくリレーショナル マッピングを確認できます。

于 2013-02-05T18:34:48.810 に答える