ORA-01000: maximum open cursors exceeded 表示進程打開的游標數超過 OPEN_CURSORS 參數限制(默認 300)。Java 中每次調用 createStatement() 或 prepareStatement() 都會在數據庫端打開一個游標,若在循環中重複創建且未關閉,極快耗盡配額。
createStatement() 後從不調用 close()。for/while 循環中反覆 createStatement() 或 prepareStatement()。TO_DATE('...') 或直接拼接字串,未使用 setDate()/setTimestamp() 綁定變量。rs.close(),導致關聯游標殘留。PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM t WHERE id = ?");
try {
for (int id : ids) {
pstmt.setInt(1, id);
ResultSet rs = pstmt.executeQuery();
try {
while (rs.next()) { /* 處理數據 */ }
} finally {
rs.close(); // 關閉 ResultSet 釋放游標
}
}
} finally {
pstmt.close(); // 循環結束關閉 Statement
}
try (PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) { /* ... */ }
} // 自動關閉 rs、pstmt,即使拋出異常
治標不治本。生產環境建議設置 500~1000,但必須配合代碼規範,否則洩漏最終仍會擊穿任何閾值。
Statement/PreparedStatement/ResultSet 的代碼塊負責在 finally 中關閉。ResultSet 立即 close(),不要等到方法結束。JdbcTemplate 或使用 Spring/MyBatis 等框架,由框架保證資源釋放。