63 votes

Spring - Est-il possible d'utiliser plusieurs gestionnaires de transactions dans une même application ?

Je suis nouveau dans Spring et je me demande s'il est possible d'utiliser plusieurs gestionnaires de transactions dans la même application ?

J'ai deux couches d'accès aux données - une pour les deux bases de données. Je me demande comment procéder pour utiliser un gestionnaire de transactions pour une couche et un autre gestionnaire de transactions pour l'autre couche. Je n'ai pas besoin d'effectuer des transactions sur les deux bases de données - pas encore. Mais j'ai besoin d'effectuer des transactions sur chaque base de données individuellement. J'ai créé une image pour aider à décrire mon problème :

alt text

Voici la configuration de mon contexte d'application :

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <context:component-scan base-package="cheetah.repositories" />
    <tx:annotation-driven />

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="accounts" />
    </bean>

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

    <bean id="transactionManager"
        class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

</beans>

Voici un exemple qui utilise cette configuration :

@Repository
public class JpaAccountRepository implements AccountRepository {

    @PersistenceContext(unitName = "cheetahAccounts")
    private EntityManager accountManager;

    @Override
    @Transactional
    public Account findById(long id) {

        Account account = accountManager.find(Account.class, id);
        return account;
    }
}

Ainsi, pour le référentiel des comptes, je veux utiliser une usine de gestion des entités avec l'unité de persistance définie sur les comptes. Cependant, pour mon référentiel de données d'entreprise, je veux utiliser un gestionnaire d'entité factory avec une unité de persistance différente. Comme je ne peux définir qu'un seul bean de gestionnaire de transactions, comment puis-je utiliser différents gestionnaires de transactions pour les différents référentiels ?

Merci pour toute aide.

85voto

Chin Huang Points 3830

Lorsque vous utilisez un @Transactional vous pouvez spécifier le gestionnaire de transactions à utiliser en ajoutant un ensemble d'attributs à un nom de haricot ou à un qualificatif. Par exemple, si votre contexte d'application définit plusieurs gestionnaires de transactions avec des qualificatifs :

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

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

Vous pouvez utiliser le qualificatif pour spécifier le gestionnaire de transactions à utiliser :

public class TransactionalService {

    @Transactional("account")
    public void setSomethingInAccount() { ... }

    @Transactional("businessData")
    public void doSomethingInBusinessData() { ... }
}

6voto

duffymo Points 188155

Cette entrée de Spring Jira discute un peu de ce problème :

https://jira.springframework.org/browse/SPR-3955

Je pense que cela pourrait être un gestionnaire de transactions par connexion si vous n'utilisez pas le commit à deux phases. Il suffit de créer deux gestionnaires de transactions et de les injecter avec la connexion appropriée.

Mais je dois poser la question suivante : pourquoi pensez-vous avoir besoin de deux gestionnaires de transactions ? Vous pouvez avoir plus d'une connexion à la base de données. Les DAO qui utilisent les connexions peuvent et doivent être instanciés par différents services, chacun d'entre eux pouvant être annoté avec ses propres paramètres transactionnels. Un seul gestionnaire peut s'occuper des deux. Pourquoi pensez-vous en avoir besoin de deux ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X