web-dev-qa-db-ja.com

Springで2つの異なるDBを使用するためのトランザクション管理を構成するにはどうすればよいですか?

2つのデータベース(MySqlとHSQLDB)があります。 2つのデータソースと2つのEntityManagerFactory Beanを構成しました。 2つの対応するJpaTransactionManager Beanを構成することもできます。

しかし、具体的なサービスクラスのトランザクションを管理するために使用する必要があるものを指定する方法がわかりません。そのために@Transactionalアノテーションを使用したいのですが、実際には指定できるtxManagerは1つだけです。

<tx:annotation-driven transaction-manager="manager"/>

この状況から抜け出す方法は何ですか?

35
Roman

JpaTransactionManagerのjavadoc はこれについていくつかアドバイスがあります:

このトランザクションマネージャは、トランザクションデータアクセスに単一のJPA EntityManagerFactoryを使用するアプリケーションに適しています。同じトランザクション内の複数のトランザクションリソースにアクセスするには、JTA(通常はJtaTransactionManagerを使用)が必要です。 JTAトランザクションに参加させるには、それに応じてJPAプロバイダーを設定する必要があることに注意してください。

つまり、対応するtxマネージャーを含む複数のエンティティマネージャーを使用している場合は、代わりに単一の JtaTransactionManager を使用することを検討する必要があります。エンティティマネージャーはJTAトランザクションに参加できる必要があります。これにより、どちらのエンティティマネージャーであるかを常に気にする必要なく、両方のエンティティマネージャーで完全なトランザクション性が得られます。

もちろん、JtaTransactionManagerには、Tomcatのようなバニラサーブレットエンジンではなく、JTAをサポートする完全なアプリケーションサーバーが必要です。

18
skaffman

transaction-manager属性なしで<tx:annotation-driven>を宣言し、次のようにトランザクションマネージャの修飾子を宣言します。

<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    <qualifier value="txManager1"/>
</bean>

この修飾子を@ Transactionalvalueとして使用して、トランザクションマネージャの1つを選択します。

@Transactional("txManager1")

または、より多くのプロパティ:

@Transactional(value = "txManager1", readOnly = true)   
19
axtavt

久しぶりの正解以来。

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で修飾子名を指定していないものを指定するために使用する必要があります

12
raksja

以下のように、application-context.xmlでそのために2つのトランザクションマネージャを指定する必要があります。

<tx:annotation-driven transaction-manager="manager1"/>
<tx:annotation-driven transaction-manager="manager2"/>

@Transactional属性は、関連するトランザクションマネージャを使用するようになります。

6
Mital Pritmani