【问题标题】:Close result set in loop using Java [duplicate]使用Java在循环中关闭结果集[重复]
【发布时间】:2018-03-10 02:55:55
【问题描述】:

这个问题应该很简单,可能会很烦人,但我仍然对使用 Java 关闭结果集表示怀疑。应该为每个语句或结果集做应该只在最终关闭?

       try {
        Class.forName(<driver class>);                
        con = DriverManager.getConnection(
            "IP", 
            "username",
            "password");
        for(String dealId : items) {
            String sql= "SQL Query";
            preparedStatement = con.prepareStatement(sql);
            rs = preparedStatement.executeQuery();
            while(rs.next()) {
                count += rs.getInt("total");                    
            }
            // Result should be closed here as the statement got executed?
        }
        System.out.println(count);
        if(items.size() == count) {
            dealsBelongToTheParty = true;
        }

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        rs.close(); // Or this is right?
        preparedStatement.close();
        if(!con.isClosed())
            con.close();
    }

【问题讨论】:

  • 最好在 finally 块中完成
  • 使用 try-with-resource 会更好
  • 您似乎在 for 循环的每次迭代中创建了一个新结果集。在这种情况下,合乎逻辑的做法是关闭 for 循环中的每一个,而不是只关闭最后剩下的任何一个。
  • 在一个 finally 块中塞满多个 close 语句是一个非常糟糕的主意。你会导致连接泄漏。
  • 您正在泄漏 ResultSets 和 PreparedStatements。您应该在每次循环时都关闭它们。幸运的是,如果您使用的是完全兼容的 JDBC 驱动程序,那么当您关闭语句时,它们都会关闭。但这对于所有目的来说可能还不够快。

标签: java jdbc


【解决方案1】:

我建议使用 Java 7 try-with-resources
(下面的代码假设在查询中使用了循环变量dealId

Class.forName(<driver class>);                
try (Connection con = DriverManager.getConnection(
        "IP", "username", "password")) {
    for(String dealId : items) {
        String sql= "SQL Query with " + dealId;
        // resources are opened by order 
        try (PreparedStatement preparedStatement = con.prepareStatement(sql);
             ResultSet rs = preparedStatement.executeQuery()) {
            while(rs.next()) {
                count += rs.getInt("total");                    
            }
        } // resources are implicitly closed in reverse order of open
    }
} catch (Exception e) {
    e.printStackTrace();
}

System.out.println(count);
if(items.size() == count) {
    dealsBelongToTheParty = true;
}

【讨论】:

  • ResultSet 也是 AutoCloseable
  • ...并且也在 try-with-resources...
  • 这种情况下不会有内存泄漏吧?你在哪里关闭了语句、结果集和连接?我在问关于关闭结果集
  • 应该在 finally 块中还是在 try 块之后完成?我担心内存泄漏。
  • @Aliy,在 try-with-resouces 中没有明确的关闭。它由编译器添加到 try 块的右括号
【解决方案2】:

https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html

“当生成它的 Statement 对象关闭、重新执行或用于从多个结果序列中检索下一个结果时,ResultSet 对象将自动关闭。”

所以,您不必担心关闭 ResultSet。

【讨论】:

  • 那为什么ResultSet实现AutoCloseable
  • @SharonBenAsher,因为它可以显式关闭。
  • OP 在for 循环的每次迭代中创建一个新语句。所以引用的文档没有涵盖他的案例。
猜你喜欢
  • 2015-01-28
  • 1970-01-01
  • 2014-04-09
  • 1970-01-01
  • 2022-10-18
  • 1970-01-01
  • 2012-11-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多