【问题标题】:How to close refcursor in spring when using simplejdbccall使用simplejdbccall时如何在spring中关闭refcursor
【发布时间】:2014-05-27 16:56:51
【问题描述】:

我正在使用 spring simpleJdbcCall 来调用 oracle 存储过程,并且我正在使用 oracle 11g。

我偶然发现了几篇帖子,这些帖子表明可能存在内存泄漏,因为引用游标没有被 spring 正确关闭。

在使用 spring simplejdbccall 时是否有显式关闭游标?还是增加oracle OPEN_CURSOR 是唯一的出路?

我计划扩大我的应用程序,使其每小时处理大约一百万笔交易。任何建议都会有所帮助。

【问题讨论】:

    标签: spring oracle jdbc


    【解决方案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());
         }
    
    }
    

    ResultSetOUT 参数也一样:

    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;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多