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?
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.