我们使用 Spring SimpleJdbcCall 来调用 Oracle 中返回游标的存储过程。看起来 SimpleJdbcCall 没有关闭游标,并且在一段时间后超出了最大打开游标数。
ORA-01000: maximum open cursors exceeded ; nested exception is java.sql.SQLException: ORA-01000: maximum open cursors exceeded spring
论坛上也有一些人遇到过这种情况,但似乎没有答案。看起来我是 spring/oracle 支持中的一个错误。
这个错误很严重,可能会影响我们未来对 Spring JDBC 的使用。
有没有人遇到过修复方法 - 或者将问题跟踪到 Spring 代码,或者找到避免该问题的解决方法?
我们使用的是 Spring 2.5.6。
这是使用 SimpleJdbcCall 的代码的新版本,它似乎没有正确关闭过程通过游标返回的结果集:
...
SimpleJdbcCall call = new SimpleJdbcCall(dataSource);
Map params = new HashMap();
params.put("remote_user", session.getAttribute("cas_username") );
Map result = call
.withSchemaName("urs")
.withCatalogName("ursWeb")
.withProcedureName("get_roles")
.returningResultSet("rolesCur", new au.edu.une.common.util.ParameterizedMapRowMapper() )
.execute(params);
List roles = (List)result.get("rolesCur")
不使用Spring JDBC的旧版本代码没有这个问题:
oracleConnection = dataSource.getConnection();
callable = oracleConnection.prepareCall(
"{ call urs.ursweb.get_roles(?, ?) }" );
callable.setString(1, (String)session.getAttribute("cas_username"));
callable.registerOutParameter (2, oracle.jdbc.OracleTypes.CURSOR);
callable.execute();
ResultSet rset = (ResultSet)callable.getObject(2);
... do stuff with the result set
if (rset != null) rset.close(); // Explicitly close the resultset
if (callable != null) callable.close(); //Close the callable
if (oracleConnection != null) oracleConnection.close(); //Close the connection
看起来 Spring JDBC 没有调用 rset.close()。如果我在旧代码中注释掉该行,那么在负载测试之后我们会得到相同的数据库异常。