java JPA 多事务管理器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/75700/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 10:57:38  来源:igfitidea点击:

JPA Multiple Transaction Managers

javaspringormjpatransactions

提问by bmw0128

I have one applicationContext.xml file, and it has two org.springframework.orm.jpa.JpaTransactionManager (each with its own persistence unit, different databases) configured in a Spring middleware custom application.

I want to use annotation based transactions (@Transactional), to not mess around with TransactionStatus commit, save, and rollback.

A coworker mentioned that something gets confused doing this when there are multiple transaction managers, even though the context file is set configured correctly (the references go to the correct persistence unit. Anyone ever see an issue?

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

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

一位同事提到,当有多个事务管理器时,即使上下文文件设置正确(引用转到正确的持久性单元。有人看到问题吗?



In your config, would you have two transaction managers? Would you have txManager1 and txManager2?

That's what I have with JPA, two different Spring beans that are transaction managers.

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

这就是我对 JPA 的看法,它是两个不同的 Spring bean,它们是事务管理器。

采纳答案by toolkit

I guess you have 2 choices

我猜你有2个选择

If your use-cases never require updates to both databases within the same transaction, then you can use two JpaTransactionManagers, but I'm not sure you will be able to use the @Transactional approach? In this case, you would need to fallback on the older mechanism of using a simple TransactionProxyFactoryBeanto define transaction boundaries, eg:

如果您的用例从不需要在同一事务中更新两个数据库,那么您可以使用两个 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 -->

If you are require a transaction spanning both databases, then you will need to use a JTA transaction manager. The APIstates:

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

This transaction manager is appropriate for applications that use a single JPA EntityManagerFactory for transactional data access. JTA (usually through JtaTransactionManager) is necessary for accessing multiple transactional resources within the same transaction. Note that you need to configure your JPA provider accordingly in order to make it participate in JTA transactions.

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

What this means is that you will need to provide a JTA transaction manager. In our application, we use config similar to the following:

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

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

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

If you are deploying within an appserver, then the spring JtaTransactionManager needs to do a lookup to the real XA-compliant JTA transaction manager provided by the appserver. However, you can also use a standalone JTA transaction manager (but I haven't tried this myself yet)

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

As for configuring the Jpa persistence provider, I'm not that familiar. What JPA persistence provider are you using?

至于配置Jpa持久化提供者,我不是很熟悉。您使用的是什么 JPA 持久性提供程序?

The code above is based on our approach, where we were using native Hibernate as opposed to Hibernate's JPA implementation. In this case, we were able to get rid of the two HibernateTransactionManager beans, and simply ensure that both SessionFactories were injected with the same JTA TM, and then use the tx:annotation-driven element.

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

Hope this helps

希望这可以帮助

回答by toolkit

The only situation in which you can have two Spring transaction managers is if you never have both transactions open at one time. This is not intrinsically to do with distributed transactions - the same restrictions apply even if you want the two datasources to have completely separate (but potentially overlapping in time) transaction lifecyles.

您可以拥有两个 Spring 事务管理器的唯一情况是,如果您永远不会同时打开两个事务。这本质上与分布式事务无关 - 即使您希望两个数据源具有完全独立(但可能在时间上重叠)的事务生命周期,同样的限制也适用。

Internally Spring's transaction managers all use Spring's TransactionSynchronizationManager which keeps a bunch of critical state in static ThreadLocal variables, so transaction managers are guaranteed to stomp all over each other's state.

Spring 内部的事务管理器都使用 Spring 的 TransactionSynchronizationManager,它在静态 ThreadLocal 变量中保存了一堆关键状态,因此事务管理器可以保证对彼此的状态进行处理。