在多数据源场景中配置Spring事务管理器的正确方法(hibernate 5.2.6)

时间:2017-01-31 13:33:22

标签: hibernate jpa spring-data-jpa wildfly transactionmanager

将我的应用程序升级到hibernate 5.2.6(5.0)和spring-core升级到4.3.6后,我开始有大量臭名昭着的"无法获取当前线程的事务同步会话" Hibernate异常。

import pandas as pd   

df1 = df.loc[pd.MultiIndex.from_arrays(edge_subset2.T)]


print(df1)

#outputs
          edge_id    edge_weight
------  ---------  -------------
(1, 2)          0       0.548814
(2, 3)          3       0.544883
(1, 4)          2       0.602763

此应用程序使用3个数据源,全部在Jboss Wildfly中配置为非XA数据源:

  1. Db1:mysql,使用旧版弃用的Criteria API使用Hibernate。
  2. Db2:mysql,普通JDBC。
  3. Db3:sql server,Hibernate with JPA CriteriaBuilder。
  4. 没有跨数据库查询。每个服务都是@Transactional,特定的服务,DAO和模型类(用于休眠)在不同的包中分开。他们之间没有参考。

    问题是,我对如何以正确的方式配置事务管理器非常不确定"。我设法实现的唯一解决方案是通过精心改变每个@transaction注释来包含转换管理器名称:

    15:13:36,907 ERROR [foo.my.CustomLdapAuthoritiesPopulator] (default task-10) Error populating authorities: javax.persistence.TransactionRequiredException: no transaction is in progress
        at org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl.java:3450)
        at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1418)
        at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1414)
        at org.springframework.orm.hibernate5.SessionFactoryUtils.flush(SessionFactoryUtils.java:144)
        at org.springframework.orm.hibernate5.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:95)
    

    从而导致以下完整的application-context.xml文件(hibernate属性,省略了xmlns名称空间)

    @Transactional(transactionManager="tmDb1")
    

    我的问题是:

    1. 应该使用多少个tx管理员?可以使用<?xml version="1.0" encoding="UTF-8"?> <beans> <task:annotation-driven /> <mvc:annotation-driven></mvc:annotation-driven> <!-- Exclude controllers --> <context:component-scan base-package="foo.my.framework, foo.my.app"> <context:exclude-filter type="regex" expression="foo\.my\.app\.web\.controllers\..*" /> </context:component-scan> <!-- DB1 Datasource Hibernate mysql --> <bean id="DB1" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:/myconnections/db1-datasource" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="dataSource" ref="DB1" /> <property name="packagesToScan"> <list> <value>foo.my.framework.domain</value> <value>foo.my.app.model</value> </list> </property> </bean> <bean id="tmDb1" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- DB2 Datasource JDBC mysql --> <bean id="DB2" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:/myconnections/db2-datasource" /> </bean> <bean id="tmDb2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="DB2" /> </bean> <!-- DB3 Datasource Hibernate SQL Server JPA CriteriaBuilder --> <bean id="DB3" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:/myconnections/db3-datasource" /> </bean> <bean id="punDB3" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="punDB3" /> <property name="dataSource" ref="DB3" /> <property name="packagesToScan"> <list> <value>foo.my.app.model.db3model</value> </list> </property> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> </property> </bean> <bean id="tmDb3" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="punDB3" /> </bean> <tx:annotation-driven transaction-manager="tmDb1" /> <tx:annotation-driven transaction-manager="tmDb2" /> <tx:annotation-driven transaction-manager="tmDb3" /> </beans> 来完成吗?我尝试了一些组合但无济于事。如果可能的话,我想只有一个交易经理。

    2. 是否有办法(有一个或多个tx-managers)来避免在<tx:jta-transaction-manager />注释中声明tx-name?

    3. 为什么在将hibernate从5.0迁移到5.2时会出现此错误?它与3 tx:注释驱动的块完美配合,无需在@Transactional注释上指明TM的名称。

    4. 从本质上讲,使用不同的数据源类型(有些是实体管理器)在春天配置多个数据源的最简洁方法是什么?

    5. 一些评论:

      • 每个数据源都在Wildfly中配置为非XA。
      • 我不介意使用容器事务管理器。
      • 所有@Service类一次只处理一个数据库。无需将事务扩展到多个数据源。

      更新1 经过一番调查后,我认为通过不在@Transactional属性中声明事务管理器名称,spring试图找到一个名为&#34; transactionManager&#34;的TM,所以(也许)这个因为所有的DAO&#39; s使用相同的默认TM有效吗?但仍然没有解释为什么它停止工作然后升级Hibernate。

0 个答案:

没有答案