I am wondering if the following code uses the try-with-resources correctly.
try (ResultSet rs = new QueryBuilder(connection, tableName(), getPaths(), searchQuery()).add(constraint).build().executeQuery()) {
while (rs.next()) {
beans.add(createBean(rs));
}
}
The arguments are not important, the only important thing is:
new QueryBuilder().build();
returns a PreparedStatement
.I completely understand that rs
will be closed, but will the PreparedStatement
also be closed, and if so, for what reason? Because the ResultSet
closes or because of the try-with-resources?
The try -with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try -with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.
You can use catch and finally blocks with try-with-resources statement just like an ordinary try statement.
If an exception is thrown from within a Java try-with-resources block, any resource opened inside the parentheses of the try block will still get closed automatically. The throwing of the exception will force the execution to leave the try block, and this will force the automatic closing of the resource.
It is possible, and in fact common, for a base class to implement AutoCloseable even though not all of its subclasses or instances will hold releasable resources.
PreparedStatement#close() will automatically close any associated result sets but the reverse is not true because statements are reusable after their result sets are closed.
Look at the javadoc of ResultSet#close():
Note: A ResultSet object is automatically closed by the Statement object that generated it when that Statement object is closed
And then Statement#close():
Note: When a Statement object is closed, its current ResultSet object, if one exists, is also closed.
This usage looks very crappy to me :
ResultSet rs=conn.createStatement().executeQuery();
If executed enough times it will leak all of the available cursors, because cursors are associated with the Statement
not with ResultSet
.
Hence to close the underlying PreparedStatement
with try-with-resources statement , just declare it within the try
statement :
A try-with-resources statement is parameterized with variables (known as resources) that are initialized before execution of the try block and closed automatically.
Look at this answer from assylias, declare the PreparedStatement
as well as ResultSet
inside the try
statement.
Since you are not looking for a memory leak, but a resource leak . The memory of the PreparedStatement
will be collected eventually and it's memory freed, as it is not referenced anymore after execution of your method given the way it is initialized , however, the resources hold by the Statement
is not closed .
You can include several resources in the try, and they will all be closed - which is necessary if you want the PreparedStatement
to be closed:
try (PreparedStatement ps = new QueryBuilder(connection, tableName(), getPaths(), searchQuery()).add(constraint).build();
ResultSet rs = ps.executeQuery();) {
while (rs.next()) {
beans.add(createBean(rs));
}
}
According to the documentation here - tryResourceClose, as I read it, it is specific to resources that are declared
.
The try-with-resources statement is a try statement that declares one or more resources.
Reading further down you see:
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)
) {
I suggest the correct answer to you issue is the following:
try{
PreparedStatement statement = new QueryBuilder(connection, tableName(), getPaths(), searchQuery())
.add(constraint).build();
ResultSet rs = statement.executeQuery())
}
As you correctly stated, rs
will be closed. This means actually that the close()
method will be invoked on rs
. So the try-with-ressource statement doesn't explictly close the PreparedStatement
in your case.
If it's closed otherwise (in context of the rs.close()
) is kind of hard to say without knowing the implementation ;-)
EDIT
As @TheNewIdiot correctly found out, your PreparedStatement
won't be closed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With