jth*_*thg 4 java hibernate ejb jdbc
在阅读了有关此错误的先前问题后,似乎所有人都认为您需要在所有数据源上启用XA.但:
有关应用程序的信息:
该应用程序是在Sun Java Application Server 9.1上运行的EJB
我使用类似下面的spring上下文来设置hibernate会话工厂:
<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>
Run Code Online (Sandbox Code Playgroud)
两个JNDI资源都是javax.sql.ConnectionPoolDatasoure.他们实际上都指向同一个连接池,但我们有两个不同的JNDI资源,因为有两个,完全独立的,表组将移动到在未来不同的数据库的可能性.
然后在代码中,我做:
sessionA = dbASessionFactory.openSession();
sessionB = dbBSessionFactory.openSession();
sessionA.beginTransaction();
sessionB.beginTransaction();
Run Code Online (Sandbox Code Playgroud)
sessionB.beginTransaction()行在这篇文章的标题中产生错误 - 有时候.我在两个不同的sun应用服务器上运行了应用程序.在一个运行它很好,另一个抛出错误.虽然它们连接到不同但等效的数据库,但我认为两台服务器的配置方式没有任何区别.
所以问题是
谢谢.
PS堆栈跟踪是:
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 ...]
Run Code Online (Sandbox Code Playgroud)
1为什么上面的代码没有启动完全独立的事务?
该应用程序.服务器为您管理事务,如果需要,可以是分布式事务.它会自动征集所有参与者.当只有一个参与者时,您没有注意到与纯JDBC事务有任何区别,但如果有多个参与者,则确实需要分布式事务,因此出现错误.
2如何强制它启动独立事务而不是分布式事务?
您可以将数据源配置为XA或Local.Spring/Hibernate的事务行为也可以配置为使用常规JDBC事务或将事务管理委派给JTA分布式事务管理器.
我建议你将数据源切换到非XA并尝试配置Spring/Hibernate以使用JDBC事务.您应该在文档中找到相关信息,这里我怀疑是要更改的行:
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager" />
Run Code Online (Sandbox Code Playgroud)
这应该基本上意味着您没有使用该应用程序.服务器分布式事务管理
3哪种配置可能导致两个应用程序服务器之间的行为差异?
如果你有完全相同的应用程序和配置,这意味着在一种情况下,只有一个参与者被列入dist.交易,而在第二种情况下有两个.一个参与者通常对应于与数据库的一个物理连接.可能是在一种情况下,您在两个不同的数据库上使用两个模式,而在第二种情况下,您在同一个物理数据库上使用两个模式?更可能的解释是数据源在两个应用程序上的配置不同.服务器.
PS:如果你使用JTA分布式事务,你应该使用UserTransaction.{begin,commit,rollback}
而不是它们的等价物Session
.