【问题标题】:Statement and Resultset close after connection close连接关闭后关闭语句和结果集
【发布时间】:2012-07-29 20:16:59
【问题描述】:

我最近搬到了一个项目,我遇到了很多这种性质的代码 - (这里使用的是 jdbc postgres 驱动)

try {
    Connection conn = pool.getAConnection(); //home-grown conn pool 
    PreparedStatement ps = ..;
    ResultSet rs = ..;
    rs = ps.executeQuery();
    ...
 } catch (SQLException se) {
    conn.close(); 
} finally {
    if (stmt != null) stmt.close();
    if (rs != null) rs.close();
}

显然,这段代码已经投入生产一段时间,没有引起任何问题。

我很难理解的是,在异常流程中,连接首先被关闭或返回到池中;然后尝试关闭语句和结果集。关闭父连接对象后执行此操作是否有意义?

由于代码的结构方式,连接释放必须在异常块中完成。这是无法改变的。 话虽如此,在连接被释放到池之后,是否可以将 stmt.close() 和 rs.close() 留在最后?

为了进一步澄清,如果我的理解是正确的(即语句和结果集必须在连接关闭之前而不是之后关闭),我需要在 catch 和 finally 之间重复一些代码。修改后的代码现在如下所示。这可以简化吗?

try {
...
} catch(Exception ex){
      if (rs != null) {
         close(rs); rs = null; // close() method impl just calls rs.close() in try-catch block
      }
      if (ps != null) {
         close(ps); ps = null;
      }
      processException( ex, con); // This method logs and then either closes the connection or releases to pool, depending on some conditions. 
      con = null;
  } finally {
      if (rs != null) {
          close(rs); 
      }
      if (ps != null) {
          close(ps); 
      }             
      if (null != con) {
          close(con);
      }
  }

只是为了透视,这段代码已经结束了——至少有 100 个左右的方法!如果可能的话,我想进一步简化这一点。 感谢您的反馈。

【问题讨论】:

    标签: jdbc


    【解决方案1】:

    finally 块中释放连接非常有意义。在 finally 块中关闭 StatementResultSet 也是如此。

    原因很简单:您确保您的StatementResultSet 在成功执行和异常情况下都被关闭。连接也是如此。我会在finally 块中做这样的事情

    try{
    
    }catch(Exception exe){
    
    }finally{
        if (stmt != null) stmt.close();
        if (rs != null) rs.close();
    
        //release connection to connection pool
    
    }
    

    另外,我相信当Statement 被关闭时,它当前的ResultSet 也被关闭。所以如果rsstmt相关联,那么我相信当你执行stmt.close()时它会被关闭

    【讨论】:

    • 谢谢您的回复。同意,我总是会在最后关闭语句和结果集。我试图在这里解决的问题(也许我没有明确说明)是 - 在上面的代码中,连接在 catch 子句中被关闭,然后是语句和最终结果集 - 顺序似乎不合逻辑。可以这样吗?运行此代码没有任何问题,但我不相信它将来不会。代码库中有很多这样的例子,这就是为什么我不愿意彻底改变它,除非花费的时间是合理的。
    • 在您发布的代码的第一部分中,您仅在发生异常时才关闭连接。完成工作后最好释放连接,无论是否发生异常。实现这一点的最佳位置是finally 块。来到您的第二段代码,为什么要在 catchfinally 块中编写相同的代码来关闭您的 resultsetpreparedstatement。反正都是多余的。把它作为你的finally 逻辑的一部分
    • 没错,但这是我必须使用的遗留代码的一个限制——关闭/释放连接必须保留在 catch 子句中。我要做的就是释放资源。由于连接是在 catch 子句中释放的,我试图在连接关闭之前关闭并释放语句和结果集。它很乱,但我不确定在连接关闭后最后这样做是否正确。
    猜你喜欢
    • 2012-12-11
    • 2020-10-24
    • 1970-01-01
    • 2010-09-11
    • 2019-02-19
    • 2017-05-24
    相关资源
    最近更新 更多