JPA多个事务管理器


问题内容

我有一个applicationContext.xml文件,它在Spring中间件自定义应用程序中配置了两个org.springframework.orm.jpa.JpaTransactionManager(每个都有自己的持久性单元,不同的数据库)。

我想使用基于注释的事务(@Transactional),以免使TransactionStatus提交,保存和回滚。

一位同事提到,即使有多个事务管理器,即使上下文文件的配置正确(引用指向正确的持久性单元。有人看到问题了吗?),这样做有些混乱。


在您的配置中,您将有两个事务管理器吗?您有txManager1和txManager2吗?

这就是JPA的功能,这是两个不同的Spring Bean,它们是事务管理器。


问题答案:

我猜你有两个选择

如果您的用例从不要求在同一事务中同时更新两个数据库,则可以使用两个JpaTransactionManager,但是我不确定您是否可以使用@Transactional方法?在这种情况下,您将需要回退到使用简单的TransactionProxyFactoryBean定义事务边界的旧机制,例如:

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

如果需要跨两个数据库的事务,则需要使用JTA事务管理器。该API的状态:

该事务管理器适用于使用单个JPA
EntityManagerFactory进行事务数据访问的应用程序。要访问同一事务中的多个事务资源,必须使用JTA(通常通过JtaTransactionManager)。请注意,您需要相应地配置JPA提供程序,以使其参与JTA事务。

这意味着您将需要提供一个JTA事务管理器。在我们的应用程序中,我们使用类似于以下内容的配置:

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

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

如果要在应用服务器中进行部署,那么spring
JtaTransactionManager需要对由该应用服务器提供的符合XA的真正JTA事务管理器进行查找。但是,您也可以使用独立的JTA事务管理器(但是我自己还没有尝试过)

至于配置Jpa持久性提供程序,我并不那么熟悉。您正在使用哪个JPA持久性提供程序?

上面的代码基于我们的方法,我们使用的是本地Hibernate,而不是Hibernate的JPA实现。在这种情况下,我们可以摆脱两个HibernateTransactionManager
bean,只需确保两个SessionFactories都注入了相同的JTA TM,然后使用tx:annotation-driven元素。

希望这可以帮助