Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用ChainedTransactionManager(JDBC+;JPA)时,不支持传播会在JDBC中创建失败的事务_Jpa_Jdbc_Spring Data_Transactional - Fatal编程技术网

使用ChainedTransactionManager(JDBC+;JPA)时,不支持传播会在JDBC中创建失败的事务

使用ChainedTransactionManager(JDBC+;JPA)时,不支持传播会在JDBC中创建失败的事务,jpa,jdbc,spring-data,transactional,Jpa,Jdbc,Spring Data,Transactional,我正在开发一个使用JDBC(DAO的扩展名参数JDBCDAOSupport)的现有Spring应用程序。配置了四个数据源,每个数据源都有自己的DataSourceTransactionManager。(尽管由于某种原因,只有一个注册了tx:annotation-driven) 我最近在应用程序中添加了JPA(SpringDataJPA),并配置了两个EntityManagerFactory(目前我不需要另外两个数据源)。我还为这些数据源配置了两个JPATransactionManager并删除了

我正在开发一个使用JDBC(DAO的扩展名参数JDBCDAOSupport)的现有Spring应用程序。配置了四个数据源,每个数据源都有自己的DataSourceTransactionManager。(尽管由于某种原因,只有一个注册了tx:annotation-driven) 我最近在应用程序中添加了JPA(SpringDataJPA),并配置了两个EntityManagerFactory(目前我不需要另外两个数据源)。我还为这些数据源配置了两个JPATransactionManager并删除了相应的DataSourceTransactionManager,因为JPATransactionManager也可以用于JDBC事务。(如果我错了,请纠正我)

似乎我需要能够拥有分布式事务,因为两个数据源(到两个不同的数据库)需要在一个服务方法中访问(通过JPA)。由于我没有设置JTA(其中一个数据库缺少XA驱动程序)所需的全部资源,我决定尝试一下Spring ChainedTransactionManager。遗憾的是,这并没有如预期的那样成功。如果我只调用一个只使用JPA的服务方法,那么一切都很好。 虽然当我调用一个使用JDBC查找的现有服务方法时,该方法的类级别@transactional注释的传播设置为NOT_SUPPORTED,然后使用JPA调用和@transactional调用另一个服务方法,但我得到一个异常:

Caused by: java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHolder@462cf9d9] for key [org.jboss.jca.adapters.jdbc.WrapperDataSource@3fbb4c32] bound to thread [http-/127.0.0.1:8080-5]
at org.springframework.transaction.support.TransactionSynchronizationManager.bindResource(TransactionSynchronizationManager.java:189) [spring-tx-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:403) [spring-orm-3.2.5.RELEASE.jar:3.2.5.RELEASE]
经过一些调试,我发现Spring中的事务被添加到“TransactionSynchronizationManager.bindResource”方法中ThreadLocal上的映射中。问题是,当使用不支持@transactional和propogation的JDBC调用时,无论如何都会进行事务并通过该方法注册。当JpaTransactionManager尝试绑定其资源时,它已经在映射上(未标记为void),这会导致错误发生

将封装JDBC调用的服务调用的传播更改为默认的“REQUIRED”,可以解决此问题。 我不知道为什么Spring在不支持事务注释的情况下仍在创建该事务。如果它创建了该事务,则不应绕过JpaTransactionManager。 所以我想知道的是,当Spring在NamedParameterJdbcDaoSupport中创建事务时,是否有某种方法可以告诉它也使用JpaTransactionManager。(实际上JdbcDaoSupport…实际上是DataSourceUtils)

我们使用的是Spring3.2.5、SpringDataJPA1.6.0,我使用的是Hibernate4.2.0作为JpaVendor

如果没有ChainedTransactionManager,则不会出现此问题

数据源:

<bean id="dataSourceCompta" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:jboss/datasources/comptaDS"/>
</bean>
<bean id="dataSourceUnisys" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:jboss/datasources/insoverDS"/>
</bean>
<bean id="dataSourceInsoverwebMysql" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:jboss/datasources/insoverWebDS"/>
</bean>
<bean id="dataSourceBatch" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:jboss/datasources/batchDS"/>
</bean>

剩余的单个JDBC事务管理器(无JPA对应项):


JPA事务管理器:

<bean id="jpaUnisysTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactoryUnisys"/>
    <qualifier value="unisys" />
</bean>
<bean id="jpaMysqlTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactoryMysql"/>
    <qualifier value="mysql" />
</bean>

我的ChainedTransactionManager:

    <bean id="chainedTransactionManager" class="org.springframework.data.transaction.ChainedTransactionManager">
    <constructor-arg>
        <list>
            <ref bean="jpaUnisysTransactionManager" />
            <ref bean="jpaMysqlTransactionManager" />
        </list>
    </constructor-arg>
</bean>

JPA实体管理器工厂:

<bean name="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
<bean id="entityManagerFactoryUnisys" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceXmlLocation" value="classpath:META-INF/some-persistence.xml"/>
    <property name="dataSource" ref="dataSourceUnisys"/>
    <property name="persistenceUnitName" value="unisysPU"/>
    <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
    <property name="jpaProperties">
        <!-- properties -->
    </property>
</bean>
<bean id="entityManagerFactoryMysql" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceXmlLocation" value="classpath:META-INF/some-persistence.xml"/>
    <property name="dataSource" ref="dataSourceCompta"/>
    <property name="persistenceUnitName" value="mysqlPU"/>
    <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
    <property name="jpaProperties">
        <!-- properties -->
    </property>
</bean>

现在我已经“修复”了这个问题,将所有类级别的事务注释更改为具有propagation.REQUIRED(默认)而不是NOT_SUPPORTED。虽然我真的不喜欢这种解决方案,因为可能有人有充分的理由将这些传播设置为不受支持。我也尝试过支持,但使用它与不支持有相同的问题:当名为ParameterJDBCDAOSupport的DAO执行查询时,Spring DataSourceUtils仍在进行事务。 当服务上没有设置事务性注释时,所有注释都可以正常工作

<bean name="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
<bean id="entityManagerFactoryUnisys" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceXmlLocation" value="classpath:META-INF/some-persistence.xml"/>
    <property name="dataSource" ref="dataSourceUnisys"/>
    <property name="persistenceUnitName" value="unisysPU"/>
    <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
    <property name="jpaProperties">
        <!-- properties -->
    </property>
</bean>
<bean id="entityManagerFactoryMysql" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceXmlLocation" value="classpath:META-INF/some-persistence.xml"/>
    <property name="dataSource" ref="dataSourceCompta"/>
    <property name="persistenceUnitName" value="mysqlPU"/>
    <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
    <property name="jpaProperties">
        <!-- properties -->
    </property>
</bean>