【问题标题】:Where to close result set在哪里关闭结果集
【发布时间】:2013-08-13 18:47:52
【问题描述】:

我得到的结果集已经关闭,我将结果集传递给其他方法。我应该在哪里关闭结果集。

public void mainTest(){

ResultSet rs= pstmt.executeQuery(query);

List list = populateRS(rs);

if(rs!=null)rs.close();
}

public List populateRS(ResultSet rs){

//work with result set
if(rs!=null)rs.close();
}

【问题讨论】:

    标签: java jdbc


    【解决方案1】:

    即使populateRS(或其他东西)抛出异常,您也应该使用try-finally 块来关闭ResultSet

    ResultSet rs;
    try {
        rs = pstmt.executeQuery(query);
        List list = populateRS(rs);
    } finally {
        if (rs != null) {
            rs.close();
        }
    }
    

    【讨论】:

    • 所以我应该关闭 mainTest 中的结果集而不是 populateRS 中的结果集。是吗? public void mainTest(){ ResultSet rs= pstmt.executeQuery(query);列表列表 = populateRS(rs); if(rs!=null)rs.close(); } public List populateRS(ResultSet rs){ //使用结果集 }
    • 是的,我认为在一种方法中创建和关闭ResultSet 总是更清晰(并且更不容易出错),并让您调用的任何其他方法只处理自己处理结果(无需担心打开、关闭、检查是否已经打开……)。
    • @Jaque 我认为您的populateRS 方法可能存在不同的问题。查看类似问题herehere
    【解决方案2】:

    如果可能,请以打开时使用的相同方法关闭。始终如一地这样做可以让代码审查人员和维护人员轻松地将资源分类到其中(显然是释放的,显然是有问题的,并且需要更多的关注)。

    其他几点说明:

    1. 使用try (...) 或在finally 中关闭,这样即使使用它的代码因异常而失败,资源也会关闭。
    2. 酌情使用@WillClose and @WillNotClose 注释,以便IDE 和findbugs 等工具能够指出问题。

    public void mainTest(){
      List<?> list;
      try (ResultSet rs = pstmt.executeQuery(query)) {
        list = populateRS(rs);
      }
      // work with list
    }
    
    public List<?> populateRS(@WillNotClose ResultSet rs){
      //work with result set
    }
    

    或者如果你被旧的 Java 卡住了:

    public void mainTest(){
      List<?> list;
      ResultSet rs = pstmt.executeQuery(query);
      try {
        list = populateRS(rs);
      } finally {
        if(rs!=null)rs.close();
      }
      // work with list
    }
    

    【讨论】:

    • @WillNotClose 注解从何而来?那是 JDK 或其他库的一部分吗?
    • @andersschuller JSR-305
    • @andersschuller,请查看我添加的链接。
    • @Jaque,在获取下一行之前检查是否还有更多行。
    • 从 Java 7 开始,使用 try 和 autoclose
    【解决方案3】:

    使用新的 try-with-resources statement,无论是否发生异常都会自动关闭 ResultSet,因为它实现了 AutoCloseable

    try-with-resources 语句是声明一个或多个资源的 try 语句。资源是程序完成后必须关闭的对象。 try-with-resources 语句确保每个资源在语句结束时关闭。

    public void mainTest()
    {
      try (ResultSet rs = pstmt.executeQuery(query)) { 
         List list = populateRS(rs);
      } catch (SQLException ex) {
    
      }
    }
    
    public List populateRS(ResultSet rs){
        // work with result set
    }
    

    【讨论】:

    • 仅从 Java 7 开始。
    【解决方案4】:

    最好在你打开的地方关闭。
    finally块中关闭所有资源是一种很好的编程习惯

           public void mainTest()
           {
             ResultSet rs = null;
             try{ 
                  rs= pstmt.executeQuery(query);
                 List list = populateRS(rs);
              }finally{
                   try {
                     rs.close();
                   } catch (SQLException ex) {
    
                   }
              }
          }
    
         public List populateRS(ResultSet rs){
    
            //work with result set
    
        }
    

    根据javadocs

    将清理代码放在 finally 块中始终是一种很好的做法,即使没有预料到异常也是如此。

    【讨论】:

      【解决方案5】:

      关闭你打开它们的地方附近的东西。在这种情况下,这将在您调用 populateRS 后的 mainTest 方法中。如果一个方法没有打开某些东西,它不应该关闭它。

      【讨论】:

      • 所以我应该关闭 mainTest 中的结果集而不是 populateRS 中的结果集。是吗? public void mainTest(){ ResultSet rs= pstmt.executeQuery(query);列表列表 = populateRS(rs); if(rs!=null)rs.close(); } public List populateRS(ResultSet rs){ //使用结果集 }
      • 我认为,只要合同明确,关闭其他传递给它的东西的方法通常是合适的。它通常通过流来完成。
      • @Jaque:是的。您可以将 rs.close 放在 finally 块中或使用 try-with-resources。
      • @Colin:可能会有例外,但这是一个简单的案例。就像戴夫牛顿所说,这是基本的关注点分离。
      【解决方案6】:

      您应该关闭mainTest 方法中的ResultSet 以隔离populateRS 方法对ResultSet 生命周期的参与。

      您应该有一个finally 块,您应该在其中关闭ResultSet。这种做法可以保证即使抛出异常,ResultSet 也会关闭。

      【讨论】:

      • 我不同意; populateRS 的职责应该是使用结果集,而不是参与其生命周期。基本的关注点分离。
      猜你喜欢
      • 2011-11-21
      • 2011-01-31
      • 2013-01-03
      • 2011-07-27
      • 2011-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多