15

我想知道以下代码是否正确使用了 try-with-resources。

try (ResultSet rs = new QueryBuilder(connection, tableName(), getPaths(), searchQuery()).add(constraint).build().executeQuery()) {
    while (rs.next()) {
        beans.add(createBean(rs));
    }
}

论据不重要,唯一重要的是:

  • new QueryBuilder().build();返回一个PreparedStatement

我完全明白这rs将被关闭,但也会PreparedStatement被关闭,如果是,是什么原因?因为ResultSet关闭还是因为资源尝试?

4

4 回答 4

19

PreparedStatement#close()将自动关闭任何关联的结果集,但反之则不然,因为语句在其结果集关闭后是可重用的。

查看ResultSet#close()的 javadoc :

注意:当 Statement 对象关闭时,生成它的 Statement 对象会自动关闭 ResultSet 对象

然后Statement#close()

注意:当 Statement 对象关闭时,其当前的 ResultSet 对象(如果存在)也将关闭。

这种用法对我来说看起来很糟糕:

ResultSet rs=conn.createStatement().executeQuery();

如果执行的次数足够多,它将泄漏所有可用的游标,因为游标与Statementnot with相关联ResultSet

PreparedStatement因此,要使用try-with-resources 语句关闭底层证券,只需在语句中声明它try

try-with-resources 语句使用变量(称为资源)参数化,这些变量在执行 try 块之前初始化并自动关闭

从 assylias 看这个答案,在声明中声明PreparedStatement以及。ResultSettry

由于您不是在寻找内存泄漏,而是在寻找资源泄漏。的内存PreparedStatement最终将被收集并释放它的内存,因为在执行您的方法后不再引用它,因为它的初始化方式,但是,由 持有的资源Statement没有关闭。

于 2013-07-22T13:03:01.277 回答
9

您可以在 try 中包含多个资源,它们都将被关闭 - 如果您想要关闭它们,这是必要的PreparedStatement

try (PreparedStatement ps = new QueryBuilder(connection, tableName(), getPaths(), searchQuery()).add(constraint).build();
        ResultSet rs = ps.executeQuery();) {
    while (rs.next()) {
        beans.add(createBean(rs));
    }
}
于 2013-07-22T13:06:15.680 回答
3

根据此处的文档 - tryResourceClose,当我阅读它时,它特定于declared.

The try-with-resources statement is a try statement that declares one or more resources.

进一步阅读,您会看到:

You may declare one or more resources in a try-with-resources statement. The following example retrieves the names of the files packaged in the zip file zipFileName and creates a text file that contains the names of these files:

 try (
      java.util.zip.ZipFile zf =
         new java.util.zip.ZipFile(zipFileName);
    java.io.BufferedWriter writer = 
        java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
  ) {

我建议您问题的正确答案如下:

try{
  PreparedStatement statement = new QueryBuilder(connection, tableName(), getPaths(), searchQuery())
       .add(constraint).build();
  ResultSet rs = statement.executeQuery()) 
}
于 2013-07-22T13:06:42.747 回答
2

如您所说,rs将关闭。这实际上意味着该close()方法将在rs. 因此, try-with-ressource 语句不会明确关闭PreparedStatement您的情况。

如果它以其他方式关闭(在上下文中rs.close())在不知道实现的情况下很难说;-)

编辑

正如@TheNewIdiot 正确发现的那样,您PreparedStatement不会被关闭。

于 2013-07-22T13:03:04.053 回答