使用simplejdbccall时如何在spring中关闭refcursor
Posted
技术标签:
【中文标题】使用simplejdbccall时如何在spring中关闭refcursor【英文标题】:How to close refcursor in spring when using simplejdbccall 【发布时间】:2014-05-27 16:56:51 【问题描述】:我正在使用 spring simpleJdbcCall 来调用 oracle 存储过程,并且我正在使用 oracle 11g。
我偶然发现了几篇帖子,这些帖子表明可能存在内存泄漏,因为引用游标没有被 spring 正确关闭。
在使用 spring simplejdbccall 时是否有显式关闭游标?还是增加oracle OPEN_CURSOR 是唯一的出路?
我计划扩大我的应用程序,使其每小时处理大约一百万笔交易。任何建议都会有所帮助。
【问题讨论】:
【参考方案1】:其实Spring JDBC不存在这样的问题。它在所有执行后关闭finally
内的所有资源。 SimpleJdbcCall
使用JdbcTemplate
:
public <T> T execute(CallableStatementCreator csc, CallableStatementCallback<T> action)
throws DataAccessException
try
...
catch (SQLException ex)
...
finally
if (csc instanceof ParameterDisposer)
((ParameterDisposer) csc).cleanupParameters();
JdbcUtils.closeStatement(cs);
DataSourceUtils.releaseConnection(con, getDataSource());
ResultSet
OUT 参数也一样:
protected Map<String, Object> processResultSet(ResultSet rs, ResultSetSupportingSqlParameter param) throws SQLException
....
finally
JdbcUtils.closeResultSet(rs);
return returnedResults;
另一方面,我在高负载系统中使用 Spring JDBC 和 Oracle 有丰富的经验,我想说的是,我们注意到 Oracle 上有足够的开放资源在峰值负载下,但在那之后它们已被正确释放。
虽然我们使用了 JBOSS Pooled DataSource
及其 TransactionMaanger
【讨论】:
谢谢Artem。这很有帮助!!【参考方案2】:我直接使用CallableStatement,我可以快速安全地释放语句和连接,尝试两种方法并测量内存消耗,它完美地解决了内存消耗和连接保留问题,证明了应用程序的许多等待和拒绝连接。
try
log.info("**** RepositoryPSostgres.getAllProducts ******** ");
Connection conn = jdbcTemplate.getDataSource().getConnection();
conn.setAutoCommit(false);
// Procedure call.
CallableStatement proc = conn.prepareCall("? = call get_all_products() ");
proc.registerOutParameter(1, Types.OTHER);
proc.execute();
ResultSet results = (ResultSet) proc.getObject(1);
**proc.close();
proc.isClosed();
conn.close();**
ArrayList <Products> resp = new ArrayList <Products>();
while (results.next())
Products resp1 = new Products();
resp1.setId(results.getInt("id"));
resp1.setName((String) results.getString("name"));
resp1.setPrice((BigDecimal) results.getBigDecimal("price"));
resp.add(resp1);
log.info("***" + results.getInt("id") + "***** ");
log.info("***" + results.getString("name") + "***** ");
log.info("***" + results.getBigDecimal("price") + "***** ");
results.close();
return resp;
catch (Exception e)
e.printStackTrace();
log.error(new StringBuffer("Error en transaccion en saldo CashPooling : ").append(e.getLocalizedMessage()).toString());
return null;
【讨论】:
以上是关于使用simplejdbccall时如何在spring中关闭refcursor的主要内容,如果未能解决你的问题,请参考以下文章
如何在 spring 中使用 SimpleJDBCCall 获取存储过程的结果以及两个结果表?
从spring boot simpleJDBCcall调用PL SQL过程时出错
SimpleJdbcCall - 执行 oracle 程序时出错