【问题标题】:Will CallableStatement.close() cause performance issueCallableStatement.close() 会导致性能问题
【发布时间】:2017-12-10 18:33:27
【问题描述】:

我有一个关于性能的问题。

我使用的应用程序是 Spring MVC 应用程序 (v3.2.9)。它托管在 WebSphere Application Server (v8.5.5) 上。它连接到一个 AS400 DB2 系统(驱动程序是 JTOpen v9.1)。我的应用程序调用 IBM AS400 系统上的存储过程。它是使用 Spring 的 JdbcTemplate.execute 方法调用的。代码如下:

jdbcTemplate.execute(new CallableStatementCreator() {
        @Override
        public CallableStatement createCallableStatement(Connection con) throws SQLException {
            CallableStatement cs = con.prepareCall("{CALL XXXXXXSP ( ?, ? )}");
            cs.setString(1, xxx);
            cs.setString(2, xxx);
            return cs;
        }
    }, 
    new CallableStatementCallback<String>() {
        @Override
        public String doInCallableStatement(CallableStatement cs)throws SQLException, DataAccessException {
            cs.execute();
            return null;
        }
    });

我们遇到了一些问题,调用此过程偶尔会引发错误“[SQL0501] Cursor C1 not open” 在打开日志记录和查看后,看起来此错误仅在应用程序尝试重新- 使用 CallableStatement。上次使用此 CallableStatement 时,相应的游标已关闭,这会导致错误(我不能 100% 确定这种重用是否是预期的行为)。该错误每天大约发生 20 次,这是一个相对较低的百分比,因为此应用程序的流量要高得多。

我的问题是,在cs.execute();之后的代码中添加cs.close();会导致代码性能下降吗?

【问题讨论】:

  • 问题出在您在 AS400 上调用的程序中。您必须在 AS400 上修复它。当没有找到记录时,我在野外看到这些关闭语句没有执行,没有用于提交控制的初始提交。我还看到在野外没有检查打开是否成功,因此获取失败。添加代码以检查 open 语句。如果打开失败,则发出关闭语句,然后发出另一个打开语句。
  • @danny117 感谢您的建议,只是想澄清一下...您所指的 open 语句和 close 语句将在 AS400 上的程序中,而不是 Java 代码中,是对吗?
  • 是的,它看起来像 as400 编码问题。我假设 close 用于关闭光标。

标签: java spring-mvc jdbc ibm-midrange


【解决方案1】:

通常你应该调用 close() 方法来关闭语句,因为它释放资源。这没有任何问题。

但是 JdbcTemplate 为你关闭语句,所以不需要它。

这是 JdbcTemplate 在执行execute(CallableStatementCreator csc, CallableStatementCallback&lt;T&gt; action) 方法结束时所做的:

JdbcUtils.closeStatement(cs);
DataSourceUtils.releaseConnection(con, getDataSource());

并且来自 CallableStatementCallback api:

 doInCallableStatement(CallableStatement cs) throws SQLException ,DataAccessException

由 JdbcTemplate.execute 调用,并带有活动的 JDBC 可调用语句。不需要关心关闭Statement 或连接,或关于处理事务:这都是 由 Spring 的 JdbcTemplate 处理。 注意:任何打开的结果集都应该 在回调实现中的 finally 块中关闭。春天 将在回调返回后关闭 Statement 对象,但这 并不一定意味着 ResultSet 资源将 关闭:Statement 对象可能会被连接池池化, 关闭调用仅将对象返回到池中,但不返回 物理关闭资源。

【讨论】:

  • 似乎任何由存储过程显式打开的结果集都需要由客户端关闭。我不确定应该在框架中的哪个位置发生。如果结果集不应该返回给调用者,那么存储过程应该已经关闭了结果集。此外,由于游标名称在作业中需要是唯一的,因此存储过程应使用比 C1 更具体的名称作为游标名称。
猜你喜欢
  • 2015-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-10
相关资源
最近更新 更多