2つのデータベース(MySqlとHSQLDB)があります。 2つのデータソースと2つのEntityManagerFactory Beanを構成しました。 2つの対応するJpaTransactionManager Beanを構成することもできます。
しかし、具体的なサービスクラスのトランザクションを管理するために使用する必要があるものを指定する方法がわかりません。そのために@Transactional
アノテーションを使用したいのですが、実際には指定できるtxManagerは1つだけです。
<tx:annotation-driven transaction-manager="manager"/>
この状況から抜け出す方法は何ですか?
JpaTransactionManagerのjavadoc はこれについていくつかアドバイスがあります:
このトランザクションマネージャは、トランザクションデータアクセスに単一のJPA EntityManagerFactoryを使用するアプリケーションに適しています。同じトランザクション内の複数のトランザクションリソースにアクセスするには、JTA(通常はJtaTransactionManagerを使用)が必要です。 JTAトランザクションに参加させるには、それに応じてJPAプロバイダーを設定する必要があることに注意してください。
つまり、対応するtxマネージャーを含む複数のエンティティマネージャーを使用している場合は、代わりに単一の JtaTransactionManager
を使用することを検討する必要があります。エンティティマネージャーはJTAトランザクションに参加できる必要があります。これにより、どちらのエンティティマネージャーであるかを常に気にする必要なく、両方のエンティティマネージャーで完全なトランザクション性が得られます。
もちろん、JtaTransactionManager
には、Tomcatのようなバニラサーブレットエンジンではなく、JTAをサポートする完全なアプリケーションサーバーが必要です。
transaction-manager属性なしで<tx:annotation-driven>
を宣言し、次のようにトランザクションマネージャの修飾子を宣言します。
<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<qualifier value="txManager1"/>
</bean>
この修飾子を@ Transactionalでvalueとして使用して、トランザクションマネージャの1つを選択します。
@Transactional("txManager1")
または、より多くのプロパティ:
@Transactional(value = "txManager1", readOnly = true)
久しぶりの正解以来。
Skaffmanは、複数のデータベースに対するJpaTransactionManagerの使いやすさの点で正しいかもしれません。
しかし、2つの異なるJpaTransactionManagerで2つの異なるデータベースを使用するための実用的なソリューションがあります。
@Bean(name = "db2TransactionManager")
public PlatformTransactionManager transactionManager2() throws NamingException {
JpaTransactionManager txManager = new JpaTransactionManager(entityManagerFactory());
return txManager;
}
@Bean
@Primary
public PlatformTransactionManager transactionManager() throws Exception {
JpaTransactionManager txManager = new JpaTransactionManager(entityManagerFactory());
txManager.setNestedTransactionAllowed(true);
return txManager;
}
@Primary
は、@Transactional
で修飾子名を指定していないものを指定するために使用する必要があります
以下のように、application-context.xmlでそのために2つのトランザクションマネージャを指定する必要があります。
<tx:annotation-driven transaction-manager="manager1"/>
<tx:annotation-driven transaction-manager="manager2"/>
@Transactional属性は、関連するトランザクションマネージャを使用するようになります。