0

我将EJB3Oracle数据库和JDBC一起使用。

我正在开发一个必须触发 25000 个UPDATE查询的应用程序。

我的代码如下:

public int updateStatus(List<String> idList) {
    Connection connection = getConnection(); // Connection initialized properly for oracle db
    statement = connection.createStatement();
    String sql = null;
    for (String id : idlist) { // idList is properly filled
        sql = "UPDATE TBLTEST SET STATUS = 'FIXED' WHERE ID = '" + id + "'";
        statement.addBatch(sql);
    }
    int[] affectedRecords = statement.executeBatch();
}

请注意,编写此方法的类被注释为

@TransactionManagement(TransactionManagementType.CONTAINER)

此代码在最多 8000 个查询时运行良好。对于 more id,它会抛出以下异常:

org.jboss.util.NestedSQLException: Transaction TransactionImple < ac, BasicAction: 0:ffffc0a80272:1652:56bd6be5:57e status: ActionStatus.ABORTED > cannot proceed STATUS_ROLLEDBACK; - nested throwable: (javax.transaction.RollbackException: Transaction TransactionImple < ac, BasicAction: 0:ffffc0a80272:1652:56bd6be5:57e status: ActionStatus.ABORTED > cannot proceed STATUS_ROLLEDBACK)
    at org.jboss.resource.adapter.jdbc.WrapperDataSource.checkTransactionActive(WrapperDataSource.java:165)
    at org.jboss.resource.adapter.jdbc.WrappedConnection.checkTransactionActive(WrappedConnection.java:843)
    at org.jboss.resource.adapter.jdbc.WrappedConnection.checkStatus(WrappedConnection.java:858)
    at org.jboss.resource.adapter.jdbc.WrappedConnection.checkTransaction(WrappedConnection.java:835)
    at org.jboss.resource.adapter.jdbc.WrappedConnection.createStatement(WrappedConnection.java:183)

任何人都可以帮助解决这个例外吗?

4

1 回答 1

1

最佳猜测:通过使用单独的 SQL 语句而不是PreparedStatement强制驱动程序将所有语句(> 400k 的字符数据)发送到数据库和数据库以解析所有 400k 字符,这将在某些时候达到限制并破坏事物(由于隐藏了导致异常的原因,异常在何处或发生了什么并不清楚)。

怎么修:

一次去寻找个别批次的“不要太多”的陈述 - 比如说...... 1000:

public int updateStatus(List<String> idList) {
    List<Integer> affectedRecords = new ArrayList<Integer>(idList.size());
    try(Connection connection = getConnection(); 
        Statement statement = connection.createStatement()) {
        int count = 0;
        for (String id : idList) {          
            statement.addBatch("UPDATE TBLTEST SET STATUS = 'FIXED' WHERE ID = '" + id + "'");
            //Execute after 1000 rows 
            if(++count % 1000 == 0) {
                int[] result = statement.executeBatch();
                //Utility Method - you need to implement to add int[] into the List
                addResults(affectedRecords, result);
                statement.clearBatch();             
            }
        }
        //In need of final execute?
        if(count % 1000 > 0) {
          // For good measure execute once more
          int[] result = statement.executeBatch();
          //Utility Method - you need to implement to add int[] into the List
          addResults(affectedRecords, result);      
        }              
    } catch(SQLException se) {
        se.printStackTrace();
    }
}
于 2016-02-12T09:15:41.333 回答