以下のコードに取り組んでいます (わかりやすくするために編集しています)。これにより、Oracle で開いているカーソルに関するいくつかの問題が発生しています。基本的に、DB からデータを選択しようとしています。返された行ごとに、選択してレコードに追加するサブデータの行が 0 行以上あります。これは現在、サブ データを読み取るためにメイン データ セットにデータを入力しながら、別の関数を呼び出すことによって実現されています。これは、1000 未満の少量の行では問題なく機能します。これは、ユーザーが使用する通常の動作範囲ですが、数万行のオーダーになる可能性があるすべての行を要求する可能性があります。大規模なボリューム選択を実行すると、ORA-01000: 開いているカーソルの最大数を超えましたエラー。コードを実行して v$open_cursors にクエリを実行すると、カーソルが落ちるまでカウントアップしていることがわかります。
sub 関数を呼び出している行をコメントアウトすると、正常に動作し、v$open_cursors のカーソル数が数カウントだけ上下に変動します。
メイン関数がその接続オブジェクトをサブ関数に渡していることに気付きました。これにより、結果のステートメントと結果セットが、コードによって閉じられているにもかかわらず、接続がまだ開いている間に開いたままになる可能性があると考えました。そのため、各関数がプールから独自の接続を取得し、完了したら閉じるようにコードを変更しようとしましたが、カーソルに違いはありませんでした。
カーソルの数を増やすことはできますが、a) 問題を覆い隠すだけであり、b) 動作させるにはばかげたほど多くのカーソルを保持する必要があり、c) 欠陥のあるコードをリリースしたくありません!
ただし、コードでカーソルを解放する方法についてのアイデアが不足しています。
public ArrayList getCustomerSearchResult(Connection con) throws AnException {
ResultSet rst = null;
PreparedStatement stmt = null;
ArrayList resultList = new ArrayList();
String sql = "---- The search SQL string --- ";
try {
stmt = con.prepareStatement(sql);
rst = stmt.executeQuery();
while(rst.next()) {
DataDTO data = new DataDTO();
data.setSomeData(rst.getString("...."));
// ##### This call is where the problem lies #####
data.setSomeSubDataAsAnArrayList(getSubDataForThisRow(data.getId(), con));
resultList.add(data);
}
} catch(Exception e) {
throw new AnException("Error doing stuff", e);
} finally{
try{
rst.close();
stmt.close();
rst = null;
stmt = null;
}catch(Exception ex){
throw new AnException("Error doing stuff", ex);
}
}
return resultList;
}
public ArrayList getSubDataForThisRow(String Id, Connection con) throws AnException {
ResultSet rst = null;
PreparedStatement stmt = null;
ArrayList resultList = new ArrayList();
String sql = "---- The search SQL string --- ";
try {
stmt = con.prepareStatement(sql);
stmt.setString(1, Id);
rst = stmt.executeQuery();
while(rst.next()) {
SubDataDTO data = new SubDataDTO();
data.setSomeData(rst.getString("...."));
resultList.add(data);
}
} catch(Exception e) {
throw new AnException("Error!", e);
} finally{
try{
rst.close();
stmt.close();
rst = null;
stmt = null;
}catch(Exception ex){
throw new AnException("Error!", ex);
}
}
return resultList;
}