Spring data - 同一事务上的两个不同数据源导致异常

Posted

技术标签:

【中文标题】Spring data - 同一事务上的两个不同数据源导致异常【英文标题】:Spring data - two different data sources on the same transaction causing abnormality 【发布时间】:2014-02-05 15:54:29 【问题描述】:

我们正在使用带有 spring 和 2 个不同 mysql 数据源的 atomikos JTA。

我们遇到了问题,

当我们在同一个 @Transactional 方法上使用两个不同的存储库(2 个不同的数据源)时,我们会得到一个错误:

Caused by: java.sql.SQLException: Unable to enlist connection the transaction

当第二个存储库对数据源执行某些操作时会发生这种情况。

我们认为这与事务管理器 (atomikos jta) 有关,当同一事务涉及 2 个不同的数据源时可能会出现问题。

这里是数据源 xml:

    <bean
    class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

<bean id="xaDataSource" class="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"
    lazy-init="true">
    <property name="pinGlobalTxToPhysicalConnection" value="true" />
    <property name="url" value="$mysql_url" />
    <property name="user" value="root" />
    <property name="password" value="xxx" />
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.managed.BasicManagedDataSource">
    <property name="initialSize" value="10" />
    <property name="maxActive" value="100" />
    <property name="maxIdle" value="15" />
    <property name="minIdle" value="10" />
    <property name="timeBetweenEvictionRunsMillis" value="10000" />
    <property name="minEvictableIdleTimeMillis" value="60000" />
    <property name="validationQuery" value="/* ping */ SELECT 1" />
    <property name="testOnBorrow" value="true" />
    <property name="testWhileIdle" value="true" />
    <property name="xaDataSourceInstance" ref="xaDataSource" />
    <property name="transactionManager" ref="atomikosTransactionManager" />
    <property name="removeAbandoned" value="true" />
    <property name="removeAbandonedTimeout" value="300" />
</bean>

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="packagesToScan" value="com.xxx.model" />
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
        </props>
    </property>
    <property name="dataSource" ref="dataSource" />
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    </property>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="database" value="MYSQL" />
            <property name="showSql" value="false" />
            <property name="generateDdl" value="false" />
        </bean>
    </property>
    <property name="jpaPropertyMap">
        <map>
            <entry key="javax.persistence.transactionType" value="JTA" />
            <entry key="hibernate.transaction.manager_lookup_class"
                value="com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup" />
            <entry key="hibernate.connection.autocommit" value="false" />
        </map>
    </property>
</bean>

<!-- shared data source -->

<bean id="shardXaDataSource" class="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"
    lazy-init="true">
    <property name="pinGlobalTxToPhysicalConnection" value="true" />
    <property name="url" value="$shared_mysql_url" />
    <property name="user" value="root" />
    <property name="password" value="xxx" />
</bean>

<bean id="shareddDataSource" class="org.apache.commons.dbcp.managed.BasicManagedDataSource">
    <property name="initialSize" value="10" />
    <property name="maxActive" value="100" />
    <property name="maxIdle" value="15" />
    <property name="minIdle" value="10" />
    <property name="timeBetweenEvictionRunsMillis" value="10000" />
    <property name="minEvictableIdleTimeMillis" value="60000" />
    <property name="validationQuery" value="/* ping */ SELECT 1" />
    <property name="testOnBorrow" value="true" />
    <property name="testWhileIdle" value="true" />
    <property name="xaDataSourceInstance" ref="shardXaDataSource" />
    <property name="transactionManager" ref="atomikosTransactionManager" />
    <property name="removeAbandoned" value="true" />
    <property name="removeAbandonedTimeout" value="300" />
</bean>

<bean id="sharedEntityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="packagesToScan" value="com.xxx.shared.model" />
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
        </props>
    </property>
    <property name="dataSource" ref="shareddDataSource" />
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    </property>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="database" value="MYSQL" />
            <property name="showSql" value="false" />
            <property name="generateDdl" value="false" />
        </bean>
    </property>
    <property name="jpaPropertyMap">
        <map>
            <entry key="javax.persistence.transactionType" value="JTA" />
            <entry key="hibernate.transaction.manager_lookup_class"
                value="com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup" />
            <entry key="hibernate.connection.autocommit" value="false" />
        </map>
    </property>
</bean>

还有transaction.xml:

    <tx:annotation-driven proxy-target-class="true" />

<tx:jta-transaction-manager
    transaction-manager="atomikosTransactionManager" />

<tx:annotation-driven transaction-manager="atomikosTransactionManager"
    proxy-target-class="true" />

<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
    init-method="init" destroy-method="close">
    <property name="forceShutdown" value="false" />
</bean>

<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
    <property name="transactionTimeout" value="300" />
</bean>

<bean id="transactionManager"
    class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="atomikosTransactionManager" />
    <property name="userTransaction" ref="atomikosUserTransaction" />
    <property name="allowCustomIsolationLevels" value="true" />
</bean>

* 编辑 (19.01.2014) *

因此,根据 M. Deinum 的帮助,我们设法使错误消失,但现在没有实际的事务发生(在例外情况下,例如没有回滚)

这是我们的新配置:

数据源.xml:

    <bean id="xaDataSource" class="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"
    lazy-init="true">
    <property name="pinGlobalTxToPhysicalConnection" value="true" />
    <property name="url" value="$mysql_url" />
    <property name="user" value="root" />
    <property name="password" value="6918001" />
</bean>

   <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="jtaDataSource" ref="xaDataSource" />
  <property name="packagesToScan" value="com.xxx.model" />
  <property name="jpaProperties">
      <props>
         <prop key="hibernate.hbm2ddl.auto">update</prop>
         <prop     key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup        </prop>
     </props>
   </property>
 <property name="jpaVendorAdapter">
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
         <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
         <property name="showSql" value="false" />
         <property name="generateDdl" value="false" />
     </bean>
 </property>
</bean>

 <bean id="shardXaDataSource" class="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"
    lazy-init="true">
    <property name="pinGlobalTxToPhysicalConnection" value="true" />
    <property name="url" value="$shared_mysql_url" />
    <property name="user" value="root" />
    <property name="password" value="6918001" />
</bean>


 <bean id="sharedEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jtaDataSource" ref="shardXaDataSource" />
<property name="packagesToScan" value="com.xxx.shared.model" />
<property name="jpaProperties">
    <props>
        <prop key="hibernate.hbm2ddl.auto">update</prop>
        <prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop>
    </props>
</property>
<property name="jpaVendorAdapter">
    <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
        <property name="showSql" value="false" />
        <property name="generateDdl" value="false" />
    </bean>
</property>

transaction.xml:

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                    http://www.springframework.org/schema/tx
                    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

<tx:annotation-driven proxy-target-class="true" /> 


 <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<property name="forceShutdown" value="false" />
 </bean>

 <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
 </bean>

 <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
 <property name="transactionManager" ref="atomikosTransactionManager" />
 <property name="userTransaction" ref="atomikosUserTransaction" />
 <property name="allowCustomIsolationLevels" value="true" />
</bean>

</beans>

* 编辑 01/20/2014 *

我们设法让它工作,但启动时出现大量警告:

   20 Jan 2014 15:14:16  WARN AbstractDataSourceBean - AtomikosDataSoureBean 'xaDataSource': poolSize equals default - this may cause performance problems!
20 Jan 2014 15:14:17  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:17  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:17  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:17  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:17  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:17  WARN JtaPlatformInitiator - HHH000427: Using deprecated    org.hibernate.transaction.TransactionManagerLookup strategy [hibernate.transaction.manager_lookup_class],        use newer org.hibernate.service.jta.platform.spi.JtaPlatform strategy instead    [hibernate.transaction.jta.platform]
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@4063a38e: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AbstractDataSourceBean - AtomikosDataSoureBean 'sharedXaDataSource': poolSize equals default - this may cause performance problems!
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN JtaPlatformInitiator - HHH000427: Using deprecated org.hibernate.transaction.TransactionManagerLookup strategy [hibernate.transaction.manager_lookup_class], use newer org.hibernate.service.jta.platform.spi.JtaPlatform strategy instead [hibernate.transaction.jta.platform]
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN AtomikosConnectionProxy - atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3d00772f: WARNING: transaction manager not running?
20 Jan 2014 15:14:18  WARN EntityManagerFactoryRegistry - HHH000436: Entity manager factory name (default) is already registered.  If entity manager will be clustered or passivated, specify a unique value for property 'hibernate.ejb.entitymanager_factory_name'
20 Jan 2014 15:14:18  WARN UserTransactionServiceImp - No properties path set - looking for transactions.properties in classpath...
20 Jan 2014 15:14:18  WARN UserTransactionServiceImp - transactions.properties not found - looking for jta.properties in classpath...
20 Jan 2014 15:14:18  WARN UserTransactionServiceImp - Failed to open transactions properties file - using default values
20 Jan 2014 15:14:18  WARN CoordinatorImp - Local heuristic termination of coordinator     10.0.50.117.tm0050100104 with state COMMITTING
20 Jan 2014 15:14:18  WARN CoordinatorImp - Local heuristic termination of coordinator 10.0.50.117.tm0050100104 with state COMMITTING
20 Jan 2014 15:14:18  WARN CoordinatorImp - Local heuristic termination of coordinator 10.0.50.117.tm0050200104 with state COMMITTING
20 Jan 2014 15:14:18  WARN CoordinatorImp - Local heuristic termination of coordinator 10.0.50.117.tm0050200104 with state COMMITTING
20 Jan 2014 15:14:18  WARN CoordinatorImp - Local heuristic termination of coordinator 10.0.50.117.tm0050300104 with state COMMITTING
20 Jan 2014 15:14:18  WARN CoordinatorImp - Local heuristic termination of coordinator 10.0.50.117.tm0050300104 with state COMMITTING
20 Jan 2014 15:14:18  WARN CoordinatorImp - Local heuristic termination of coordinator 10.0.50.117.tm0050400104 with state COMMITTING

新的配置是:

<bean id="xaDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
    init-method="init" destroy-method="close">
    <property name="xaDataSourceClassName">
        <value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value>
    </property>
    <property name="uniqueResourceName"><value>xaDataSource</value></property>      
     <property name="xaProperties">
        <props>
            <prop key="url">$mysql_url</prop>
            <prop key="user">root</prop>
            <prop key="password">xxx</prop>
        </props>
    </property>
</bean>

<bean id="sharedXaDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
    init-method="init" destroy-method="close">
    <property name="xaDataSourceClassName">
        <value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value>
    </property>
    <property name="uniqueResourceName"><value>sharedXaDataSource</value></property>
    <property name="xaProperties">
        <props>
            <prop key="url">$shared_mysql_url</prop>
            <prop key="user">root</prop>
            <prop key="password">xxx</prop>
        </props>
    </property>
</bean>

【问题讨论】:

【参考方案1】:
<tx:annotation-driven proxy-target-class="true" />

<tx:jta-transaction-manager
    transaction-manager="atomikosTransactionManager" />

<tx:annotation-driven transaction-manager="atomikosTransactionManager"
    proxy-target-class="true" />

<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
    init-method="init" destroy-method="close">
    <property name="forceShutdown" value="false" />
</bean>

<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
    <property name="transactionTimeout" value="300" />
</bean>

<bean id="transactionManager"
    class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="atomikosTransactionManager" />
    <property name="userTransaction" ref="atomikosUserTransaction" />
    <property name="allowCustomIsolationLevels" value="true" />
</bean>

您的配置有缺陷并且包含重复,这可能会使 spring 感到困惑。 JtaTransactionManager&lt;tx:jta-transaction-manager /&gt; 都创建了一个 JtaTransactionManager

接下来您的&lt;tx:annotation-driven &gt; 应该指向JtaTransactionManager,但它指向UserTransactionManager

所以首先修复你的配置:

<tx:annotation-driven proxy-target-class="true" />

<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
    init-method="init" destroy-method="close">
    <property name="forceShutdown" value="false" />
</bean>

<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
    <property name="transactionTimeout" value="300" />
</bean>

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="atomikosTransactionManager" />
    <property name="userTransaction" ref="atomikosUserTransaction" />
    <property name="allowCustomIsolationLevels" value="true" />
</bean>

假设您使用的是最新的 Spring 3.2 版本,而不是在您的 LocalContainerEntityManagerFactoryBean 上注入 jtaDataSource 属性,而不是注入 jtaDataSource,接下来您的 jpaPropertiesjpaPropertiesMap 可以被清理。

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jtaDataSource" ref="xaDataSource" />
    <property name="packagesToScan" value="com.xxx.model" />
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            <prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop>
        </props>
    </property>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
            <property name="showSql" value="false" />
            <property name="generateDdl" value="false" />
        </bean>
    </property>
</bean>

hibernate.connection 属性在您注入 Spring 托管数据源时毫无用处。由于jtaDataSource 的注入,javax.persistence.transactionType 的 jpaProperty 可以被删除。 HibernateJpaVendorAdapter 已经设置了HibernateJpaDialect,您可以使用databasePlatform 属性来指定方言。

关于您的数据源,您应该对数据源使用 Atomikos 包装器,以便它们了解 Atomikos。为此,请使用 AtomikosDataSourceBean 而不是 xa 为您的 JDBC 驱动程序提供的数据源。

<bean id="xaDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
    <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
    <property name="uniqueResourceName" value="xaDataSource"/>      
     <property name="xaProperties">
        <props>
            <prop key="url">$mysql_url</prop>
            <prop key="user">root</prop>
            <prop key="password">xxx</prop>
        </props>
    </property>
</bean>

最后,您使用BasicDataSource 作为对休眠的引用,而您应该使用启用(和包装)xa 的数据源。

【讨论】:

M.Deinum,现在没有抛出错误,这是个好消息!。但是,现在没有为我的所有实体(来自任一数据源)发出回滚。例如,如果我的服务使用@Transactional 进行了注释并且我在其中保留了一个实体,如果在没有回滚后抛出错误:(,我已经用我所做的更改编辑了我的原始帖子。谢谢! 日志没有回滚或者数据库没有回滚?你正在使用 MySQL,所以还要确保你使用事务表类型(InnoDB 而不是 MyISAM)。您可能希望为org.springframework 启用调试日志记录并查看会发生什么(如果 tx 正确启动等)。 谢谢 Deinum,我们按照您的建议做了,我们的日志中有错误。我们把它放在原帖上(*** edit2 ***) 这是一条调试消息,您不能手动回滚(但必须将事务标记为仅回滚)。不应该是你的问题,如上所述检查你的数据库。我在您的堆栈跟踪中错过的是表明 spring 是此事务设置的一部分(我没有看到 spring transactioninterceptor 等)。 Transactioninterceptor 无处可寻:/ 它可能是什么?为什么 spring 不是这个交易的一部分?这个管弦乐队是否还有我们在原帖中没有提到的其他必需配置?【参考方案2】:

试试这个:在你的事务管理器上添加:

<qualifier value="transactionManager1"/> 

示例:

<bean id="transactionManager1" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory1" />
    <qualifier value="transactionManager1"/>
</bean>

然后在你的 DAO 实现中做这样的事情:

@Repository("Users1DAO")
public class Users1DAOJpaImp implements Users1DAO 

    @PersistenceContext(unitName="datasources1")
    @Qualifier("transactionTemplate1")
    private EntityManager em;

    @Override
    @Transactional(value="transactionManager1",  readOnly = false, propagation = Propagation.MANDATORY)
    public void save(Users1 user) 
        em.persist(user);
    


【讨论】:

以上是关于Spring data - 同一事务上的两个不同数据源导致异常的主要内容,如果未能解决你的问题,请参考以下文章

在同一事务中删除后的 Spring Data JPA 计数

Spring Data Rest 中同一实体的多个存储库

spring data jpa使用spring data jpa时,关于service层一个方法中进行删除和插入两种操作在同一个事务内处理

同一服务器上的两个项目具有不同的端口,但客户端(Angular 6)无法调用服务器(Spring Boot)

Spring事务控制

处理事务中的 spring-data-rest 应用程序事件