“本地事务已经具有1个非XA资源:不能添加更多的资源”错误 [英] "Local transaction already has 1 non-XA Resource: cannot add more resources" error

查看:230
本文介绍了“本地事务已经具有1个非XA资源:不能添加更多的资源”错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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


  1. 如果我不想要分发的
    事务怎么办?如果我想要
    在两个不同的
    数据库上同时启动事务,我该怎么办,但是
    在一个数据库
    上提交事务并在$ b上回滚事务$ b另一个?

  2. 我想知道我的代码
    是否实际启动了一个分布式的
    事务。它看起来像我是

    数据库的每一个开始完全独立的
    交易。

有关应用程序的信息:



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



我使用像下面的spring上下文来设置hibernate会话工厂:

  bean id =dbADatasourceclass =org.springframework.jndi.JndiObjectFactoryBean> 
< property name =jndiNamevalue =jdbc / dbA/>
< / bean>

< bean id =dbASessionFactoryclass =org.springframework.orm.hibernate3.LocalSessionFactoryBean>
< property name =dataSourceref =dbADatasource/>
< property name =hibernateProperties>
hibernate.dialect = org.hibernate.dialect.Oracle9Dialect
hibernate.default_schema = schemaA
< / property>
< property name =mappingResources>
[映射资源...]
< / property>
< / bean>

< bean id =dbBDatasourceclass =org.springframework.jndi.JndiObjectFactoryBean>
< property name =jndiNamevalue =jdbc / dbB/>
< / bean>

< bean id =dbBSessionFactoryclass =org.springframework.orm.hibernate3.LocalSessionFactoryBean>
< property name =dataSourceref =dbBDatasource/>
< property name =hibernateProperties>
hibernate.dialect = org.hibernate.dialect.Oracle9Dialect
hibernate.default_schema = schemaB
< / property>
< property name =mappingResources>
[映射资源...]
< / property>
< / bean>

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



然后在代码中,我做:

  sessionA = dbASessionFactory.openSession(); 
sessionB = dbBSessionFactory.openSession();
sessionA.beginTransaction();
sessionB.beginTransaction();有时候,sessionB.beginTransaction()行会在这篇文章的标题中产生错误。我在两个不同的sun应用服务器上运行应用程序。一个运行得很好,另一个抛出错误。我没有看到两台服务器配置的区别,尽管它们连接到不同但相当的数据库。



所以问题是


  1. 为什么上述代码没有启动
    完全独立的交易?

  2. 如何强制它启动
    独立交易而不是
    a分发交易?

  3. 什么配置可能会导致两个应用程序之间的
    行为的差异
    服务器?

谢谢。



堆栈跟踪是:

 本地事务已经有1个非XA资源:无法添加更多的资源。 
在com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.enlistResource(J2EETransactionManagerOpt.java:124)
在com.sun.enterprise.resource.ResourceManagerImpl.registerResource(ResourceManagerImpl.java:144)
在com.sun.enterprise.resource.ResourceManagerImpl.enlistResource(ResourceManagerImpl.java:102)
在com.sun.enterprise.resource.PoolManagerImpl.getResource(PoolManagerImpl.java:216)
在com.sun .enterprise.connectors.ConnectionManagerImpl.internalGetConnection(ConnectionManagerImpl.java:327)
在com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:189)
在com.sun.enterprise.connectors .ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:165)
在com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:158)
在com.sun.gjc.spi.base.DataSource .getConnection(DataSource.java:108)
在org.springframework.orm.hibernate3.LocalDataSourc eConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:82)
在org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)
在org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java: 167)
在org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:142)
在org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:85)
在org .hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1354)
在[应用代码...]


解决方案


1为什么上述代码不完全独立交易开始?


该应用程序。服务器管理您的交易,如果需要,可以将其作为分布式事务。它自动招募所有参与者。当只有一个参与者时,您不会注意到与简单的JDBC事务有任何差异,但是如果有多个事务,则需要一个分布式事务,因此出现错误。


2如何强制它开始独立交易,而不是
分发交易?


您可以将数据源配置为是XA或本地。 Spring / Hibernate的事务行为也可以配置为使用常规JDBC事务或将事务管理委托给JTA分布式事务管理器。



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

 < bean id =txManager
class =org /spar/

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


3什么配置可能会导致
两个应用程序服务器之间的差异?


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



PS:如果您使用JTA分布式事务,则应使用 UserTransaction。{begin,commit,rollback} 而不是在 Session 上的等效项。


After reading previous questions about this error, it seems like all of them conclude that you need to enable XA on all of the data sources. But:

  1. What if I don't want a distributed transaction? What would I do if I want to start transactions on two different databases at the same time, but commit the transaction on one database and roll back the transaction on the other?
  2. I'm wondering how my code actually initiated a distributed transaction. It looks to me like I'm starting completely separate transactions on each of the databases.

Info about the application:

The application is an EJB running on a Sun Java Application Server 9.1

I use something like the following spring context to set up the hibernate session factories:

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

Both of the JNDI resources are javax.sql.ConnectionPoolDatasoure's. They actually both point to the same connection pool, but we have two different JNDI resources because there's the possibility that the two, completely separate, groups of tables will move to different databases in the future.

Then in code, I do:

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

The sessionB.beginTransaction() line produces the error in the title of this post - sometimes. I ran the app on two different sun application servers. On one runs it fine, the other throws the error. I don't see any difference in how the two servers are configured although they do connect to different, but equivalent databases.

So the question is

  1. Why doesn't the above code start completely independent transactions?
  2. How can I force it to start independent transactions rather than a distributed transaction?
  3. What configuration could cause the difference in behavior between the two application servers?

Thanks.

P.S. the stack trace is:

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?

The app. server manages the transaction for you which can, if necessary, be a distributed transaction. It enlists all the participants automatically. When there's only one participant, you don't notice any difference with a plain JDBC transaction, but if there are more than one, a distributed transaction is really needed, hence the error.

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

You can configure the datasource to be XA or Local. The transactional behavior of Spring/Hibernate can also be configured to use either regular JDBC transactions or delegate the management of transactions to the JTA distributed transaction manager.

I suggest you switch the datasource to non-XA and try to configure Spring/Hibernate to use the JDBC transactions. You should find the relevant information in the documentation, here what I suspect is the line to change:

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

This should essentially means that you are not using the app. server distributed transaction manager.

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

If you have really exactly the same app and configuration, this means that in one case only one participant is enlisted in the dist. transaction, while there are two in the 2nd case. One participant corresponds to one physical connection to a database usually. Could it be that in one case, you use two schema on two different databases, while in the 2nd case you use two schema on the same physical database? A more probable explanation would be that the datasource were configured differently on the two app. server.

PS: If you use JTA distributed transactions, you should use UserTransaction.{begin,commit,rollback} rather than their equivalent on the Session.

这篇关于“本地事务已经具有1个非XA资源:不能添加更多的资源”错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆