【问题标题】:Spring Hibernate @transactional one service method two transactionManager?Spring Hibernate @transactional 一服务方法二事务管理器?
【发布时间】:2014-07-08 13:10:42
【问题描述】:

我想知道是否可以在一种服务方法中使用两个事务管理器。 因为由于客户端 mysql db 配置的限制,我们在一个数据库中有 2 个不同的数据源,即每个 schema 一个 user/pwd/url。这就是为什么我必须配置两个事务管理器。现在,当涉及到服务实现时,我遇到了问题。见以下代码:

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

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

    }
    ...
}

如果我使用此 Code Pattern,我总是会遇到异常

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

如果我分别运行这两种方法,效果很好。 我错过了什么?或者这里还有其他工作? 任何建议将不胜感激。

顺便说一句:我的一些配置

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

【问题讨论】:

  • doTwo 上的 @Transactional 在从 doOne 调用时被忽略。由于 Spring 为 aop 使用代理,因此只拦截外部方法调用。
  • @M. Deinum 所以你的意思是没有更好的解决方案?
  • 您必须将 bean 注入自身并在其上调用方法(就像使用 EJB 一样)。
  • 谢谢,我可以试试。

标签: java spring hibernate jakarta-ee


【解决方案1】:

因为你想在一个事务中加入两个数据源,你需要 XA(Global) Transaction。

因此你需要:

  1. 设置 Spring JTA 事务管理器
  2. 您的 Hibernate 属性应使用 JTA 平台设置
  3. 您的数据源连接应该是 XA 投诉
  4. 您需要一个应用服务器 JTA 事务管理器或一个独立的 tarnsaction 管理器(Bitronix、Atomikos、JOTM)
  5. 您将需要两个会话工厂配置,一个用于每个单独的数据源。
  6. 您不会有两个事务管理器:t1 和 t2,但是您将登记两个事务性 XA 数据源,它们将自动登记在同一个全局事务中,这意味着您将有两个 XA 连接登记在同一个全局事务中全球交易。 XA 事务将使用 2PC 协议在提交时提交这两个资源。

查看此Bitronix Hibernate example

【讨论】:

  • 我发现这篇文章byteslounge.com/tutorials/… 试过了,它有效!!!非常感谢。只有一个问题,如果我使用 Bitronix 或 Atomikos,我应该担心 c3p0 解决的典型 mysql 连接问题吗?换句话说,我应该也嵌入 c3p0 还是他们有自己的解决方案?
  • Bitronix 有自己的 XA 投诉池。它们的池和事务管理语义之间有非常密切的关系,因此您不应该嵌入其他连接池。 c3pO 工作正常,但用于资源本地事务。如果您想尝试最快的非 XA CP,请查看 HikariCP。
  • 总之,Bitronix 会像 c3p0 一样处理连接问题吗?
  • 我只能假设您在说“c3pO 连接问题”时指的是“连接池”? Bitronix 将为您提供一个独立的 JTA 事务管理器以及它自己的连接池支持。如果您需要额外的指标和监控,您还应该查看FlexyPool
【解决方案2】:

你有几个选择:

  1. 将 bean 注入自身并使用引用调用 doTwo()。这确实违背了 IoC 和 AOP 的整体理念,所以我不推荐它。
  2. 切换到编译时编织。 Spring(实际上是 AspectJ 编译器)将在编译时将字节码添加到您的类中,而不是使用代理。这种方法有利有弊。有关详细信息,请参阅this page
  3. 使用加载时间编织。与 #2 相同,只是您的类在加载时而不是在编译时进行修改。 IMO,Java 类加载已经够复杂了。我确信这对某些人来说非常有用,但我个人会避免这种情况。
  4. 正如 Vlad 指出的那样,您可以使用 JTA 和 XA。
  5. 在调用 doTwo() 之前,在 doOne() 中针对事务管理器 2 启动一个新事务。 programmatic transaction management 上的 RTFM。
  6. 查看ChainedTransactionManager。它本质上聚合了多个事务管理器,并在提交/回滚方面做出了“最大努力”。这不像 Vlad 的解决方案那样真正的两阶段提交。

除了 Vlad 的解决方案 (#4) 之外的所有这些都有可能使数据库处于不一致的状态。您需要使用 JTA/XA/两阶段提交来确保在某个 TX 管理器在提交时抛出异常的情况下保持一致性。

【讨论】:

  • 我不知道 ChainedTransactionManager,但如果您最多有一个非 XA 数据源,您可以从 Bitronix TM 支持的Last resource Commit optimization 中受益。
猜你喜欢
  • 1970-01-01
  • 2014-06-18
  • 2014-11-30
  • 2019-03-30
  • 2012-10-16
  • 2017-07-30
  • 2023-02-16
  • 1970-01-01
  • 2011-05-19
相关资源
最近更新 更多