web-dev-qa-db-fra.com

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

Je suis nouveau sur Spring et je me demande s'il est possible d'utiliser de nombreux 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 allez-vous utiliser un gestionnaire de transactions pour une couche et un gestionnaire de transactions différent pour l'autre couche. Je n'ai pas encore besoin d'effectuer de transactions sur les deux bases de données. 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 ma configuration de 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;
    }
}

Donc, pour le référentiel de comptes, je veux utiliser une fabrique de gestionnaire d'entités avec l'unité de persistance définie sur comptes. Cependant, avec mon référentiel BusinessData, je souhaite utiliser une fabrique de gestionnaire d'entités avec une unité de persistance différente. Étant donné que 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.

60
Brian DiCasa

Lorsque vous utilisez un @Transactional annotation, vous pouvez spécifier le gestionnaire de transactions à utiliser en ajoutant un ensemble d'attributs à un nom de bean 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() { ... }
}
82
Chin Huang

Cette entrée de Spring Jira aborde un peu le problème:

https://jira.spring.io/browse/SPR-3955

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

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

6
duffymo