2012-08-27 119 views
2

我使用批量更新準備了數以百萬計的記錄語句,但最終還是遇到了以下錯誤在運行時> 400K的記錄執行後。ORA-01000:最大打開的遊標超出批量更新的PreparedStatement

值java.sql.SQLException:ORA-01000:最大打開的遊標超出

我不知道這是由下面的代碼

try{  
conn = ConnectionManager.getConnection(); 
// turn off autocommit 
conn.setAutoCommit(false); 

PreparedStatement stmt = conn.prepareStatement(query); 

//for each of the records to be updated 
for(int k=0;k<objects.length;k++) { 

    stmt.setString(1, objects[k].getValueA()); 
    stmt.setString(2, objects[k].getValueB()); 

    stmt.addBatch(); 

    //running batch execute on every 10000 records 
    if(k%10000 == 0 || k == objects.length-1) { 
     // submit the batch for execution 
     int[] updateCounts = stmt.executeBatch(); 

     conn.commit(); 

     if(k < objects.length-1) 
     { 
      stmt.close(); 
      stmt = conn.prepareStatement(query); 
     } 
    } 
} 
}catch(Exception e) { 
    e.printStackTrace(); 
}finally { 
    if(conn!=null){ 
     conn.close(); 
    } 
} 

,從而引起PreparedStatement的是在提交連接後關閉並用新的PreparedStatement替換。我不確定是否重複提交相同的連接可能會導致此問題。

任何人都可以提出問題的解決方案或建議更好的體系結構來處理預準備語句的批處理更新。

P/S:錯誤行實際上指向刪除語句執行,但我不認爲這是根本原因,如前面前批量更新準備的語句代碼添加這個問題不存在。

try { 
    if (hasData) { 
     conn = ConnectionManager.getConnection(); 
     CommonStore.deleteRecords(conn, queryStr); //the error point to this line 
     hasData = false; 
    } 
}catch(Exception e) { 
    e.printStackTrace(); 
}finally { 
    if(conn!=null){ 
     conn.close(); 
    } 
} 

感謝您的任何建議

+0

之後調用PreparedStatement.clearParameters()你可以調整'OPEN_CURSORS' ...但是無論如何,確保你清理了你的ResultSet's。 – oldrinb

+0

爲什麼你要關閉你的'stmt'對象並且'create'又是一樣的?爲什麼不重新使用相同的'stmt'而不關閉? – Sujay

+0

@Sujay是正確的;嘗試'PreparedStatement.clearParameters' – oldrinb

回答

0

一兩件事,我觀察到的是這樣的:

if(k < objects.length-1) 
{ 
    stmt.close(); 
    stmt = conn.prepareStatement(query); 
} 

而不是closingstmt對象,我會建議重新使用。這只是一個可以避免的開銷。

我不認爲它會起任何作用,關閉並重新打開同一PreparedStatement。另外,你可以考慮在addBatch()

相關問題