ORA-01000: maximum open cursors exceeded
ORA-00604: error occurred at recursive SQL level 1
ora-01000: maximum open cursors exceeded:表示已经达到一个进程打开的最大游标数。
1.主要原因:Java代码在执行(Stored Procedure)conn.createStatement()和conn.prepareStatement()时,相当于在数据库中打开了一个cursor。尤其是,如果你的createStatement和prepareStatement是在一个循环里面的话,就会非常容易出现这个问题。因为游标一直在不停的打开,而且没有关闭。
一般来说,Java中createStatement和prepareStatement都应该要放在循环外面,而且使用了这些Statment后,及时关闭。最好是在执行了一次executeQuery、executeUpdate等之后,如果不需要使用结果集(ResultSet)的数据,就马上将Statment关闭。
对于出现ORA-01000错误这种情况,单纯的加大open_cursors并不是好办法,那只是治标不治本。实际上,代码中的隐患并没有解除.而且,绝大部分情况下,open_cursors只需要设置一个比较小的值,就足够使用了,除非有非常特别的要求。
2.解决方案:
1)从源头上解决方案(建议)
检查代码,把涉及到打开链接的地方,用完之后,千万别忘记关掉。
session.doWork(new org.hibernate.jdbc.Work() {
@Override
public void execute(Connection connection) throws SQLException {
CallableStatement cs = connection.prepareCall(prepareCallSql);
cs.setString(1, params);
cs.setClob(2, connection.createClob());
cs.registerOutParameter(2, Types.CLOB);
cs.execute();
Reader reader = cs.getClob(2).getCharacterStream();
try {
resultBuffer.append(IOUtils.toString(reader));
} catch (IOException e) {
e.printStackTrace();
} finally {
/*force close io will ignores nulls and special case*/
//IOUtils.closeQuietly(reader);
/*close connect*/
if(cs != null) { try { cs.close();} catch(Exception e) { e.printStackTrace(); } }
}
}
});
2)临时解决方案(不建议)
通过修改oracle系统参数:将OPEN_CURSORS 的值设置得足够大,以避免应用程序用尽所有打开的游标。应用程序不同,该值也不同。即便会话打开的游标数未达 OPEN_CURSORS 指定的数量(即设置的值高于实际需要的值), 也不会增加系统开销。
补充:
IOUtils 简要说明(More refer to https://blog.csdn.net/woshiwxw765/article/details/7538872/)
该类为input/output操作提供了通用静态方法, 包括功能:
•closeQuietly——这些关闭一个流的方法将忽略nulls和例外的情况。
•toXxx /read-这些方法从一个流读取数据。
• write这些方法将数据写到一个流里。
copy——这些方法用于从一个流的所有的数据复制到另一个流。
•contentEquals——这些方法用于比较两个流的内容。