2008-09-16 14 views
11

J'ai un fichier applicationContext.xml et deux org.springframework.orm.jpa.JpaTransactionManager (chacun avec sa propre unité de persistance, différentes bases de données) configurés dans une application personnalisée de middleware de Spring.

Je veux utiliser l'annotation des transactions sur la base (@Transactional), de ne pas mess avec TransactionStatus commit, enregistrer et rollback.

Un collègue de travail mentionné que quelque chose se confond faire quand il y a des gestionnaires de transactions multiples, même si le fichier de contexte est défini correctement configuré (les références vont à l'unité de persistance correcte. Tout le monde jamais vu un problème?Gestionnaires de transactions multiples JPA


Dans votre configuration, auriez-vous deux gestionnaires de transactions? auriez-vous txManager1 et txManager2?

C'est ce que j'ai avec JPA, deux différents grains de printemps qui sont les gestionnaires de transactions.

Répondre

9

Je suppose que vous avez 2 choix

Si vos cas d'utilisation ne nécessitent jamais de mises à jour des deux bases de données dans la même transaction, vous pouvez utiliser deux JpaTransactionManagers, mais je ne suis pas sûr que vous pourrez utiliser l'approche @Transactional ? Dans ce cas, vous devez fallback sur le mécanisme ancien de l'utilisation d'un simple TransactionProxyFactoryBean pour définir les limites de transaction, par exemple:

<bean id="firstRealService" class="com.acme.FirstServiceImpl"/> 
<bean id="firstService" 
    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> 
    <property name="transactionManager" ref="firstJpaTm"/> 
    <property name="target" ref="firstRealService"/> 
    <property name="transactionAttributes"> 
     <props> 
      <prop key="insert*">PROPAGATION_REQUIRED</prop> 
      <prop key="update*">PROPAGATION_REQUIRED</prop> 
      <prop key="*">PROPAGATION_REQUIRED,readOnly</prop> 
     </props> 
    </property> 
</bean> 
<!-- similar for your second service --> 

Si vous êtes besoin d'une transaction couvrant les deux bases de données, alors vous aurez besoin d'utiliser un JTA gestionnaire de transactions Le API indique:

Ce gestionnaire de transactions est approprié pour les applications qui utilisent un seul JPA EntityManagerFactory pour l'accès aux données transactionnelles. JTA (généralement via JtaTransactionManager) est nécessaire pour accéder à plusieurs ressources transactionnelles au sein d'une même transaction. Notez que vous devez configurer votre fournisseur JPA en conséquence afin de le faire participer aux transactions JTA.

Cela signifie que vous devrez fournir un gestionnaire de transactions JTA. Dans notre application, nous utilisons config similaire à ce qui suit:

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

<bean id="txManager" 
    class="org.springframework.transaction.jta.JtaTransactionManager"> 
    <property name="transactionManagerName" value="appserver/jndi/path" /> 
</bean> 

Si vous déployez dans un serveur d'applications, le printemps JtaTransactionManager doit faire une recherche pour le vrai gestionnaire de transactions JTA XA conforme fournie par le serveur d'applications. Cependant, vous pouvez également utiliser un gestionnaire de transaction JTA autonome (mais je ne l'ai pas encore essayé)

En ce qui concerne la configuration du fournisseur de persistance JPA, je ne suis pas familier. Quel fournisseur de persistance JPA utilisez-vous?

Le code ci-dessus est basé sur notre approche, où nous utilisions Hibernate native par opposition à la mise en œuvre JPA Hibernate. Dans ce cas, nous avons pu se débarrasser des deux haricots HibernateTransactionManager, et simplement faire en sorte que les deux SessionFactories ont été injectés avec le même JTA TM, puis utilisez le tx: annotation élément entraîné.

Hope this helps

+0

pouvez-vous fournir l'exemple de code ou POC de jtaTransaction avec plusieurs bases de données? – dhroove

+0

[Spring JTA transactions de ressources multiples dans Tomcat avec l'exemple Atomikos] (http://www.javacodegeeks.com/2013/07/spring-jta-multiple-resource-transactions-in-tomcat-with-atomikos-example.html) – anasanjaria

3

La seule situation dans laquelle vous pouvez avoir deux gestionnaires de transactions de printemps est si vous n'avez jamais deux transactions ouvertes à un moment donné.Ceci n'est pas intrinsèquement lié aux transactions distribuées - les mêmes restrictions s'appliquent même si vous voulez que les deux sources de données aient des styles de vie de transaction complètement séparés (mais pouvant se chevaucher dans le temps).

En interne Les gestionnaires de transactions de Spring utilisent tous la méthode TransactionSynchronizationManager de Spring qui conserve un tas d'états critiques dans les variables ThreadLocal statiques, de sorte que les gestionnaires de transactions sont assurés de s'écraser l'un sur l'autre.