Bre*_*ood 8 java oracle spring jdbc
我们使用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支持中的bug.
这个bug很关键,可能影响我们将来使用Spring JDBC.
有没有人遇到过修复 - 要么将问题跟踪到Spring代码,要么找到避免问题的解决方法?
我们使用的是Spring 2.5.6.
这是使用SimpleJdbcCall的代码的新版本,它似乎无法正确关闭proc通过游标返回的结果集:
...
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().如果我在旧代码中注释掉该行,那么在加载测试之后我们会得到相同的数据库异常.
经过多次测试后我们解决了这个问题.它是我们如何使用spring框架和oracle客户端以及oracle DB的组合.我们正在创建新的SimpleJDBCCalls,它们使用oracle JDBC客户端的元数据调用,这些调用作为游标返回,而这些游标未被关闭和清理.我认为这是Spring JDBC框架中一个如何调用元数据然后不关闭游标的错误.Spring应该从光标中复制元数据并正确关闭它.我没有打算用spring打开jira问题,因为如果你使用最佳实践,那么bug就不会被展示出来.
调整OPEN_CURSORS或任何其他参数是解决此问题的错误方法,只是延迟它出现.
我们通过将SimpleJDBCCall移动到单个DAO中来解决它/修复它,因此我们调用的每个oracle proc只打开一个游标.这些游标在应用程序的生命周期内是开放的 - 我认为这是一个错误.只要OPEN_CURSORS大于SimpleJDBCCall对象的数量,就不会有麻烦.
| 归档时间: | 
 | 
| 查看次数: | 16863 次 | 
| 最近记录: |