Pergunta

Eu tenho um arquivo applicationContext.xml e ele possui dois org.springframework.orm.jpa.JpaTransactionManager (cada um com sua própria unidade de persistência, bancos de dados diferentes) configurados em um aplicativo personalizado de middleware Spring.

Quero usar transações baseadas em anotações (@Transactional), para não mexer com commit, salvamento e reversão do TransactionStatus.

Um colega de trabalho mencionou que algo fica confuso ao fazer isso quando há vários gerenciadores de transações, mesmo que o arquivo de contexto esteja configurado corretamente (as referências vão para a unidade de persistência correta.Alguém já viu um problema?


Na sua configuração, você teria dois gerenciadores de transações?Você teria txManager1 e txManager2?

Isso é o que tenho com o JPA, dois beans Spring diferentes que são gerenciadores de transações.

Foi útil?

Solução

Eu acho que você tem 2 opções

Se seus casos de uso nunca exigirem atualizações em ambos os bancos de dados na mesma transação, você poderá usar dois JpaTransactionManagers, mas não tenho certeza se conseguirá usar a abordagem @Transactional.Neste caso, você precisaria recorrer ao mecanismo antigo de usar um simples TransaçãoProxyFactoryBean para definir limites de transação, por exemplo:

<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 -->

Se você precisar de uma transação abrangendo ambos os bancos de dados, precisará usar um gerenciador de transações JTA.O API afirma:

Esse gerenciador de transações é apropriado para aplicativos que usam um único JPA EntityManagerFactory para acesso a dados transacionais.JTA (geralmente por meio de JtaTransactionManager) é necessário para acessar vários recursos transacionais na mesma transação.Observe que você precisa configurar seu provedor JPA adequadamente para que ele participe de transações JTA.

O que isso significa é que você precisará fornecer um gerenciador de transações JTA.Em nossa aplicação, usamos uma configuração semelhante à seguinte:

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

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

Se você estiver implantando em um appserver, o spring JtaTransactionManager precisará fazer uma pesquisa no gerenciador de transações JTA real compatível com XA fornecido pelo appserver.No entanto, você também pode usar um gerenciador de transações JTA independente (mas ainda não tentei fazer isso)

Quanto à configuração do provedor de persistência Jpa, não estou familiarizado.Qual provedor de persistência JPA você está usando?

O código acima é baseado em nossa abordagem, onde estávamos usando o Hibernate nativo em oposição à implementação JPA do Hibernate.Nesse caso, conseguimos nos livrar dos dois beans HibernateTransactionManager e simplesmente garantir que ambos SessionFactories foram injetados com o mesmo JTA TM e, em seguida, usar o elemento tx:annotation-driven.

Espero que isto ajude

Outras dicas

A única situação em que você pode ter dois gerenciadores de transações Spring é se você nunca tiver as duas transações abertas ao mesmo tempo.Isso não tem a ver intrinsecamente com transações distribuídas - as mesmas restrições se aplicam mesmo se você quiser que as duas fontes de dados tenham ciclos de vida de transação completamente separados (mas potencialmente sobrepostos no tempo).

Internamente, todos os gerenciadores de transações do Spring usam o TransactionSynchronizationManager do Spring, que mantém vários estados críticos em variáveis ​​​​ThreadLocal estáticas, para que os gerenciadores de transações tenham a garantia de pisar no estado uns dos outros.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top