java.sql.SQLException : could not use local transaction commit in a global transaction

标签 java transactions sqlexception distributed-transactions xa

我们的应用程序有两个 Oracle 实例(两台物理机)和一个架构。 我们正在使用 weblogic 应用服务器。应用程序使用启用了 XA 事务的数据源。

我有一个 bean 管理的 EJB,我所做的 -

  1. 更新表中的一些数据然后提交
  2. 提交 Oracle 作业
  3. 再次更新表中的一些数据然后提交

这里我收到错误 - java.sql.SQLException: 无法在全局事务中使用本地事务提交。

奇怪的是,这个错误并不是每次执行都会出现,而是在 7-8 次执行中出现 1 次。

现在我的问题是

  1. 如果我使用启用 XA 的事务,Bean 管理的事务有何意义?
  2. 为什么每次执行时都没有遇到?

谢谢。

下面是代码-

DataObject.updateDataAndReturnCount(" UPDATE EOD_Trn_BatchProcess SET iJobNo = ?, szParameters = ?  WHERE iProcessSeqNo = ? ", conn, new String[]{null, strParameters, (String)mapParameters.get("__PROCESS_SEQ_NO")});
conn.commit();

String strStatement = "{? = call submitProcAsJob(?, ?)}";
//String strStatement = "begin ? := submitProcAsJob(?, ?); end;";
CallableStatement pStmt = conn.prepareCall(strStatement);
pStmt.registerOutParameter(1, OracleTypes.NUMBER);
pStmt.setObject(2, strJobName);
pStmt.setObject(3, strInstanceNo);
pStmt.execute();
vString strJobNo = pStmt.getString(1);
vpStmt.close();

DataObject.updateData(" UPDATE EOD_Trn_BatchProcess SET iJobNo = ?, szParameters = ?  WHERE iProcessSeqNo = ? ", conn, new String[]{strJobNo, strParameters, (String)mapParameters.get("__PROCESS_SEQ_NO")});
conn.commit();

这里需要第一次提交,因为我想保存调用期间使用的参数,即使作业提交失败。(或前面的任何事情。)

最佳答案

异常的原因是全局事务下不能手动调用commit()/rollback,只能将其标记为回滚。您有以下三种选择:

  1. 抛出异常,取决于ejb-jar.xml/weblogic-ejb-jar.xml,默认是对于任何RuntimeException,事务被标记为回滚;

  2. 在发生 CheckedException 时或在需要时调用 EJBContext.setRollbackOnly() 方法;

  3. 如果同一事务下的所有资源都没有发生上述情况,那么事务管理器迟早会提交该事务。

事务管理器负责为你commit()/rollback()事务,这样它就有机会与 不同的资源(例如两个oralce db)。您可以通过google关键字“两阶段事务”或“全局事务”查看详细信息,这是我发现的: Global Transaction

至于你的问题

  1. 如果我使用启用 XA 的事务,Bean 管理的事务有何意义?

    如果 ejb-jar.xml 中的事务属性启用事务传播,则 Bean 管理的事务是“全局事务”。全局事务需要数据源启用XA,即jdbc驱动程序本身是XA类驱动程序,例如oracle.jdbc.xa.client.OracleXADataSource,或者启用XA的瘦驱动程序oracle.jdbc.OracleDriver(模拟两阶段事务,但不是真正的事务)

  2. 为什么每次执行都没有遇到?

    我不知道为什么,我猜驱动程序有某种机制来检查规则是否被破坏。或者事务属性配置为支持,所以如果调用者有事务上下文,那么你的ejb就在全局事务下,否则不是。

希望我的回答对您有所帮助,祝您好运!

关于java.sql.SQLException : could not use local transaction commit in a global transaction,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15501655/

相关文章:

apache-kafka - 卡夫卡生产者抛出错误尝试从状态 IN_TRANSACTION 到状态 IN_TRANSACTION 的无效转换

java - 为什么我无法调试 DatabaseMetaData?

java - 在闪存驱动器上运行 Apache Derby

transactions - Redis 中的顺序监视调用

java - ejb 中事务未回滚

c# - 如何知道抛出 SqlException 的实际问题?

java - 将 Web 应用程序与 Quickbooks 集成时出现 Oauth 授权问题

java - 如何使用osgi在CQ5中显示 "hello world"

java - 为什么服务器端对 URL 的长度有限制?

java - 如何通过英文的 String.format 返回格式化的数字?