java.sql.SQLException:无法在全局事务中使用本地事务提交

时间:2013-03-19 14:03:21

标签: java transactions sqlexception distributed-transactions xa

我们有两个oracle (两个物理机器)的实例和一个用于我们应用程序的模式。 我们正在使用weblogic应用服务器。 application使用已启用XA事务的数据源。

我有一个bean管理的EJB,我在哪里 -

  1. 更新表格中的一些数据,然后提交
  2. 提交oracle工作
  3. 再次更新表中的一些数据,然后提交
  4. 这里我收到错误 - java.sql.SQLException:无法在全局事务中使用本地事务提交。

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

    现在我的问题是

    1. 如果我使用启用了XA的事务,那么bean管理事务的意义是什么?
    2. 为什么每次执行都没有遇到?
    3. 感谢。

      下面是代码 -

      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();
      

      这里首先提交是必需的,因为我想保存调用期间使用的参数,即使作业提交失败。(或者前面的任何事情。)

2 个答案:

答案 0 :(得分:1)

异常的原因是你无法在全局事务下动态调用commit()/ rollback,你只能将其标记为回滚。你有三个选择:

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

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

  3. 如果同一交易下的所有资源都没有上述情况发生,交易经理迟早会提交。

  4. 事务管理器负责为您执行commit()/ rollback()事务,以便它有机会与之合作 不同的资源(例如两个oralce db)。你可以通过gooble关键词“两阶段交易”或“全局交易”检查细节,这是我发现的: Global Transaction

    关于你的问题

    1. 如果我使用启用XA的事务,那么bean管理事务的意义是什么?

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

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

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

    3. 我希望我的回答有所帮助,祝你好运!

答案 1 :(得分:0)

我遇到了同样的问题,当我将本地事务设置为自动提交时,false解决了问题。

Connection.setAutoCommit(false)

我猜你正在使用一个2字的交易,如果你没有在第一步提交怎么办?