java - "Local transaction already has 1 non-XA Resource: cannot add more resources"错误

标签 java hibernate jdbc ejb

阅读之前有关此错误的问题后,似乎所有问题都得出结论,您需要在所有数据源上启用 XA。但是:

  1. 如果我不想要一个分布式的怎么办 交易?如果我想我会怎么做 在两个不同的开始交易 同时数据库,但是 在一个数据库上提交事务 并回滚交易 另一个?
  2. 我想知道我的代码如何 实际上发起了分布式 交易。在我看来我是 开始完全分开 对每个交易 数据库。

关于应用程序的信息:

应用程序是运行在 Sun Java Application Server 9.1 上的 EJB

我使用类似于以下 spring 上下文的东西来设置 hibernate session 工厂:

<bean id="dbADatasource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="jdbc/dbA"/>
</bean>

<bean id="dbASessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dbADatasource" />
    <property name="hibernateProperties">
        hibernate.dialect=org.hibernate.dialect.Oracle9Dialect
        hibernate.default_schema=schemaA
    </property>
    <property name="mappingResources">
        [mapping resources...]
    </property>
</bean>

<bean id="dbBDatasource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="jdbc/dbB"/>
</bean>

<bean id="dbBSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dbBDatasource" />
    <property name="hibernateProperties">
        hibernate.dialect=org.hibernate.dialect.Oracle9Dialect
        hibernate.default_schema=schemaB
    </property>
    <property name="mappingResources">
        [mapping resources...]
    </property>
</bean>

这两个 JNDI 资源都是 javax.sql.ConnectionPoolDatasoure 的。它们实际上都指向同一个连接池,但我们有两个不同的 JNDI 资源,因为这两个完全独立的表组将来可能会移动到不同的数据库。

然后在代码中,我做:

sessionA = dbASessionFactory.openSession();
sessionB = dbBSessionFactory.openSession();
sessionA.beginTransaction();
sessionB.beginTransaction();

sessionB.beginTransaction() 行会在这篇文章的标题中产生错误 - 有时。我在两个不同的 sun 应用程序服务器上运行该应用程序。一个运行良好,另一个则抛出错误。尽管这两个服务器确实连接到不同但等效的数据库,但我看不出它们的配置有何不同。

那么问题是

  1. 为什么上面的代码没有启动 完全独立的交易?
  2. 如何强制启动它 独立交易而不是 分布式事务?
  3. 什么配置可能导致差异 两个应用程序之间的行为 服务器?

谢谢。

附言堆栈跟踪是:

Local transaction already has 1 non-XA Resource: cannot add more resources. 
at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.enlistResource(J2EETransactionManagerOpt.java:124) 
at com.sun.enterprise.resource.ResourceManagerImpl.registerResource(ResourceManagerImpl.java:144) 
at com.sun.enterprise.resource.ResourceManagerImpl.enlistResource(ResourceManagerImpl.java:102) 
at com.sun.enterprise.resource.PoolManagerImpl.getResource(PoolManagerImpl.java:216) 
at com.sun.enterprise.connectors.ConnectionManagerImpl.internalGetConnection(ConnectionManagerImpl.java:327) 
at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:189) 
at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:165) 
at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:158) 
at com.sun.gjc.spi.base.DataSource.getConnection(DataSource.java:108) 
at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:82) 
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446) 
at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167) 
at org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:142) 
at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:85) 
at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1354) 
at [application code ...]

最佳答案

1 Why doesn't the above code start completely independent transactions?

应用程序。服务器为您管理事务,如有必要,它可以是分布式事务。它会自动征集所有参与者。当只有一个参与者时,您不会注意到与普通 JDBC 事务有任何区别,但如果有多个参与者,则确实需要分布式事务,因此会出现错误。

2 How can I force it to start independent transactions rather than a distributed transaction?

您可以将数据源配置为be XA or Local . Spring/Hibernate 的事务行为也可以配置为使用常规 JDBC 事务或将事务管理委托(delegate)给 JTA 分布式事务管理器。

我建议您将数据源切换到非 XA 并尝试配置 Spring/Hibernate 以使用 JDBC 事务。您应该在 documentation 中找到相关信息,这里我怀疑是要更改的行:

<bean id="txManager" 
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager" />

这基本上意味着您没有使用该应用程序。服务器分布式事务管理器。

3 What configuration could cause the difference in behavior between the two application servers?

如果您拥有完全相同的应用程序和配置,这意味着在一种情况下只有一名参与者加入了 dist。交易,而在第二种情况下有两个。一个参与者通常对应一个到数据库的物理连接。会不会是在第一种情况下,您在两个不同的数据库上使用了两个模式,而在第二种情况下,您在相同 物理数据库上使用了两个模式?更可能的解释是数据源在两个应用程序上的配置不同。服务器。

PS:如果您使用 JTA 分布式事务,您应该使用 UserTransaction.{begin,commit,rollback} 而不是它们在 Session 上的等价物。

关于java - "Local transaction already has 1 non-XA Resource: cannot add more resources"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2878597/

相关文章:

java - 在不启动事务的情况下通过 Hibernate 对 MySQL 数据库运行查询的含义是什么?

java - 看不懂这个Java GridLayout程序

java - Hibernate PersistenceContext session 刷新

sql - 在 Grails 中使用 groovy.sql.Sql 或 JDBC 进行连接池和准备好的语句

java - 在 JDBC 查询中使用表名作为参数的安全方法

java - 如何使用 GridLayout 从 JFrame 获取组件?

java - GXT 3.0 网格小部件搜索

Hibernate - AnnotationConfiguration 已弃用

java - Hibernate 查询不从同一事务返回新添加的记录

jdbc - 在哪里可以下载与 JDK 1.5 兼容的 DB2 JDBC 驱动程序?