我正在处理下面的代码(为清楚起见进行了编辑),这给我在 Oracle 中打开游标带来了一些问题。基本上我正在尝试从数据库中选择数据,并且对于返回的每一行,有 0 行或更多行要选择并附加到记录中的子数据。目前这是通过在填充主数据集以读取子数据时调用另一个函数来实现的。这适用于少于 1000 行的少量行。虽然这是用户将使用的正常操作范围,但他们可能会请求所有行,这些行可能是数千行的 10 行。进行大容量选择会导致ORA-01000:超出最大打开游标错误。如果我运行代码并查询 v$open_cursors ,则可能会看到游标计数不断增加,直到它倒下。
如果我注释掉调用子函数的行,它可以正常工作,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;
}