简体   繁体   English

跨越两个 Hibernate 事务管理器的一种服务方法上的 Spring @Transactional

[英]Spring @Transactional on one service method spanning over two Hibernate transaction managers

I was wondering if it is possible to use two transaction manager in one service methods.我想知道是否可以在一种服务方法中使用两个事务管理器。 Because due to the limitation of client's mysql db configuration, we have got 2 different datasources within one database, ie, one user/pwd/url per schema.因为由于客户端mysql db配置的限制,我们在一个数据库中有2个不同的数据源,即每个模式一个user/pwd/url。 Thats why i have to configured two transaction managers.这就是为什么我必须配置两个事务管理器。 Now I got problem when it comes to the service implementation.现在,当涉及到服务实现时,我遇到了问题。 See the following code:请参阅以下代码:

public class DemoService{
    ...
    @Transactional(value = "t1")
    public doOne(){
        doTwo();
    }

    @Transactional(value = "t2")
    public doTwo(){

    }
    ...
}

if I using this code pattern, i always got the exception如果我使用此代码模式,我总是会遇到异常

org.hibernate.HibernateException: No Session found for current thread

If i run the two methods seperately, it workd fine.如果我分别运行这两种方法,它工作正常。 Did i miss something?我错过了什么? Or there is other work around here?或者这里还有其他工作? Any advice would be appreciated.任何意见,将不胜感激。

btw: some of my configuration顺便说一句:我的一些配置

    <bean id="sessionFactorySso" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="mappingLocations">
        <list>
            <value>classpath*:sso.vo/*.hbm.xml</value>
        </list>
    </property>

    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="generateDdl">true</prop>
            <prop key="hibernate.dialect">${dialect} </prop>
        </props>
    </property>
    <property name="dataSource" ref="dataSourceSso"/>
</bean>

<bean id="dataSourceSso" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass" value="${driver}"/>
    <property name="jdbcUrl" value="${sso.url}"/>
    <property name="user" value="${sso.username}"/>
    <property name="password" value="${sso.password}"/>
         <!-- these are C3P0 properties -->
    <property name="acquireIncrement" value="2" />
    <property name="minPoolSize" value="1" />
    <property name="maxPoolSize" value="2" />
    <property name="automaticTestTable" value="test_c3p0" />
    <property name="idleConnectionTestPeriod" value="300" />
    <property name="testConnectionOnCheckin" value="true" />
    <property name="testConnectionOnCheckout" value="true" />
    <property name="autoCommitOnClose" value="true" />
    <property name="checkoutTimeout" value="1000" />
    <property name="breakAfterAcquireFailure" value="false" />
    <property name="maxIdleTime" value="0" />
</bean>

<bean id="transactionManagerSso" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactorySso"/>
    <qualifier value="sso" />
</bean>

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

Because you want to enlist two data sources in one transaction you need XA(Global) Transaction.因为您想在一个事务中登记两个数据源,所以您需要 XA(Global) Transaction。

Therefore you need to:因此,您需要:

  1. Set the Spring JTA transaction manager设置 Spring JTA 事务管理器
  2. You Hibernate properties should use the JTA platform settings您的 Hibernate 属性应该使用 JTA 平台设置
  3. Your data source connections should be XA complaint您的数据源连接应该是 XA 投诉
  4. You need an application server JTA transaction manager or a stand-alone tarnsaction manager (Bitronix, Atomikos, JOTM)您需要一个应用服务器 JTA 事务管理器或一个独立的 tarnsaction 管理器(Bitronix、Atomikos、JOTM)
  5. You will need two session factory configurations, one for each individual data source.您将需要两个会话工厂配置,一个用于每个单独的数据源。
  6. And you won't have two transaction managers: t1 and t2, but instead you will enlist two transactional XA data sources that will be automatically enlisted in the same global transaction, meaning you will have two XA connections being enlisted in the same global transaction.而且您不会有两个事务管理器:t1 和 t2,但是您将征用两个事务性 XA 数据源,它们将自动征入同一个全局事务中,这意味着您将有两个 XA 连接征入同一个全局事务中。 The XA transaction will use the 2PC protocol to commit both resources upon commit time. XA 事务将使用 2PC 协议在提交时间提交这两个资源。

Checkout this Bitronix Hibernate example .查看这个Bitronix Hibernate 示例

You have a few options:你有几个选择:

  1. Inject the bean into itself and use the reference to call doTwo().将 bean 注入自身并使用引用调用 doTwo()。 This really goes against the whole idea of IoC and AOP so I don't recommend it.这确实违背了 IoC 和 AOP 的整体理念,所以我不推荐它。
  2. Switch to compile time weaving.切换到编译时编织。 Rather than using proxies, Spring (actually the AspectJ compiler) will add the bytecode to start/stop transactions to your class at compile time. Spring(实际上是 AspectJ 编译器)将在编译时将字节码添加到您的类中,而不是使用代理。 There are pros and cons to this approach.这种方法有利有弊。 See this page for more details.有关详细信息,请参阅此页面
  3. Use load time weaving.使用加载时间编织。 Same as #2 except that your classes are modified as they are loaded rather than at compile time.与 #2 相同,只是您的类在加载时而不是在编译时进行修改。 IMO, Java classloading is complicated enough. IMO,Java 类加载已经够复杂了。 I'm sure this works great for some folks but I personally would avoid this.我确信这对某些人来说非常有用,但我个人会避免这种情况。
  4. As Vlad pointed out, you can use JTA and XA.正如 Vlad 指出的那样,您可以使用 JTA 和 XA。
  5. Start a new transaction against transaction manager 2 within doOne() before calling doTwo().在调用 doTwo() 之前,在 doOne() 中针对事务管理器 2 启动一个新事务。 RTFM on programmatic transaction management . RTFM 关于程序化事务管理
  6. Check out ChainedTransactionManager .查看ChainedTransactionManager It essentially aggregates multiple transaction managers and does a "best effort" with commit/rollback.它本质上聚合了多个事务管理器,并在提交/回滚方面做出了“最大努力”。 This is NOT a true two-phase commit like Vlad's solution.这不是像 Vlad 的解决方案那样真正的两阶段提交。

All of these except for Vlad's solution (#4) have the potential to leave the databases in an inconsistent state.除了 Vlad 的解决方案(#4)之外,所有这些都有可能使数据库处于不一致的状态。 You need to use JTA/XA/two-phase commit to ensure consistency in the event that one of the TX managers throws an exception at commit time.您需要使用 JTA/XA/两阶段提交来确保在其中一个 TX 管理器在提交时引发异常的情况下的一致性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用两个带有Spring和Hibernate注释的事务管理器和会话工厂 - Using two transaction managers and session factories with spring & hibernate annotations Spring @Transactional方法 - 参与交易 - Spring @Transactional method - participating transaction 具有@Transactional注释的多个事务管理器 - Multiple transaction managers with @Transactional annotation 多个事务管理器-在运行时选择一个-Spring - Multiple transaction managers - Selecting a one at runtime - Spring Spring中的多个事务管理器,并在运行时选择一个 - Multiple transaction managers in spring and select one at runtime Spring MVC和Hibernate中如何在单个事务中管理从服务层对DAO的两种方法调用 - How to manage two method calls to a DAO from a service layer in single transaction in Spring MVC and Hibernate Spring / Hibernate @Transactional 不刷新事务,如果后跟第二个 @Transactional 调用 - Spring / Hibernate @Transactional not flushing transaction if followed by a second @Transactional call 当来自另一个事务的延迟加载的 Hibernate 对象被传递给方法时,Spring @Transactional 不起作用 - Spring @Transactional not working when Hibernate object with lazy loading coming from another transaction is passed down to method Spring @Transactional方法中没有事务启动 - No transaction starts within Spring @Transactional method Spring事务在@Transactional方法中处理JMSTemplate - Spring transaction handling JMSTemplate inside @Transactional method
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM