Sample code:
aStmt = aConn.prepareStatement(aQuery);
aRset = aStmt.executeQuery(cQuery);
while (cRset.next()) {
//stuff to determine value of parm1
aStmt.setString(1, parm1);
aRset = aStmt.executeQuery();
//more stuff
}
Do I have to close aStmt and aRset after every loop inside the while statement? Or will reusing them in the succeeding loops release the memory/resources used from the previous loops?
If you want to test, whether your resultset gets closed or not, you can use a while loop to iterate over the result set and inside the while loop, create another query and assign it to same result set. You will see that an Exception will be thrown..
You should explicitly close Statements , ResultSets , and Connections when you no longer need them, unless you declare them in a try -with-resources statement (available in JDK 7 and after). Connections to Derby are resources external to an application, and the garbage collector will not close them automatically.
You should explicitly close your Statement and PreparedStatement objects to be sure. ResultSet objects might also be an issue, but as they are guaranteed to be closed when the corresponding Statement/PreparedStatement object is closed, you can usually disregard it.
Reusing a PreparedStatementOnce a PreparedStatement is prepared, it can be reused after execution. You reuse a PreparedStatement by setting new values for the parameters and then execute it again.
The behavior of resultsets and (prepared) statements is explicitly documented in the Java API. I suggest that you read the actual documentation (and the JDBC spec) to get the details.
The Statement
API says:
By default, only one
ResultSet
object perStatement
object can be open at the same time. Therefore, if the reading of oneResultSet
object is interleaved with the reading of another, each must have been generated by differentStatement
objects. All execution methods in theStatement
interface implicitly close a statment's currentResultSet
object if an open one exists.
(emphasis mine).
In your specific code, when you call aStmt.executeQuery()
, the old ResultSet
assigned to aRset
is implicitly closed by the driver. That said, it would be better to explicitly close it yourself (or use Java 7 try-with-resources), to prevent you from forgetting to close the ResultSet
in the last iteration through the loop.
Now to the PreparedStatement
: When you prepare a statement (in general, implementation can vary), the query is sent to the server for compilation. On execution the parameters for that specific execution is sent to the server. Calling close()
on aStmt
would result in the prepared statement being deallocated on the server, that is clearly NOT what you want here as you want to re-use the statement with different values for its parameter.
So in short
ResultSet
is not technically necessary here (except for the last ResultSet
created), but it is better to do it explicitlyPreparedStatement
when you are done with it.Using try-with-resources is one way to remove part of the confusion on these issues, as your code will automatically release resources when it is done with it (at the end of the scope of use):
try (
ResultSet cRset = cStmt.executeQuery(cQuery);
PreparedStatement aStmt = aConn.prepareStatement(aQuery);
) {
while (cRset.next()) {
//stuff to determine value of parm1
aStmt.setString(1, parm1);
try (ResultSet aRset = aStmt.executeQuery()) {
//more stuff
}
}
}
At the end of this piece of code all JDBC resources are correctly closed (in the right order, even if exceptions occurred etc)
No, you may not close the ResultSet
and Statement
inside the while
loop.
You have to close them after the loop.
Also if you want to reuse the PreparedStatement
then you may not close it until you're ready with your processing.
Best rule is to close such resources in the same block as they're created. In your case the best thing to do is to close the resources in a finally
block after catching the SQLException
.
E.g.
try {
aStmt = aConn.prepareStatement(aQuery);
cRset = cStmt.executeQuery(cQuery);
while (cRset.next()) {
//stuff to determine value of parm1
aStmt.setString(1, parm1);
try {
aRset = aStmt.executeQuery();
} finally {
aRset.close();
}
//more stuff
}
} catch (SQLException ex) {
// Do error handling
} finally {
// Close Resultset
}
In Java 7 you can use try with resources.
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