Closing PreparedStatements - java

Does use of PreparedStatements and ResultSets creates a "new database instance" everytime they are used?
Or, whith other words, if I use a PreparedStatement and a ResultSet, should I close them after every use or once I finish?
Example:
while (...){
p = connection.prepareStatement(...);
r = p.executeQuery();
while (r.next()) {
....
}
}
// We close at the end. Or there are any other p and r still opened...?
p.close();
r.close();
OR
while (...){
p = connection.prepareStatement(...);
r = p.executeQuery();
while (r.next()) {
....
}
p.close();
r.close();
}
NOTE: Of course I would use try and close properly, this is just an example.

You should close every one you open. When you create a prepared statement or result set the database allocates resources for those, and closing them tells the database to free those resources (it's likely the database will reallocate these resources eventually after a timeout period, but calling close lets the database know it can go ahead and clean up). Your second example is better, except I'd close the result set before the prepared statement.
So with try blocks included it would look like:
while (...){
PreparedStatement p = connection.prepareStatement(...);
try {
ResultSet r = p.executeQuery();
try {
while (r.next()) {
....
}
} finally {
try {
r.close();
} catch (SQLException e) {
// log this or something -- prevent these from masking original exception
}
}
}
finally {
try {
p.close();
} catch (SQLException e) {
// log this or something -- prevent these from masking original exception
}
}
}
Catching the exceptions from the close is ugly, but if you have an exception thrown during execution of the prepared statement, or during traversal of the result set, you want to make sure that you see it, and not an exception thrown when closing the prepared statement or result set (which is due to some network glitch you can't do anything about anyway).
Also be aware that using try-with-resources will work, except that if you have a case where the database operation succeeds but calling close results in an exception then the exception will get thrown.
I recommend people use the spring-jdbc library (which handles closing everything for you) instead of cranking out iffy or verbose jdbc by hand.

The first way is better.
However, you should know that you can re-use prepared statements (hence the name "prepared") if the SQL you are using is the same each time. For example:
//Note: try/catch/finally blocks removed for brevity
p = connection.prepareStatement(...);
while (...){
r = p.executeQuery();
while (r.next()) {
....
}
r.close();
}
p.close();

Related

Java: Poor error handling, Throw inside Finally

I have the following code which I am running through fortify. Why it gets marked for poor error handling, throw inside finally?
private String getResourceContent(String fileName) throws IOException {
try (InputStream resource = ErrorResource.classLoader.getResourceAsStream(fileName)) {
return new String(resource.readAllBytes(), StandardCharsets.UTF_8);
} catch (NullPointerException n) {
throw new ErrorDescriptorException(
String.format("Error loading Error description data from Resource file [%s].", fileName), n);
}
}
Explanation
This is explained very well in the official documentation (see Poor Error Handling: Throw Inside Finally). Let me quickly quote the important sections:
Using a throw statement inside a finally block breaks the logical progression through the try-catch-finally.
In Java, finally blocks are always executed after their corresponding try-catch blocks and are often used to free allocated resources, such as file handles or database cursors. Throwing an exception in a finally block can bypass critical cleanup code since normal program execution will be disrupted.
So you can easily bypass cleanup code by doing that, which leads to resource leaks.
Although not directly visible in your code, you actually have a hidden finally block since you are using try-with-resources which automatically closes the resource in a finally block.
Also see Throwing an exception inside finally where this was already discussed.
Example
Here is an example from the official documentation:
public void processTransaction(Connection conn) throws FileNotFoundException {
FileInputStream fis = null;
Statement stmt = null;
try {
stmt = conn.createStatement();
fis = new FileInputStream("badFile.txt");
...
} catch (FileNotFoundException fe) {
log("File not found.");
} catch (SQLException se) {
// handle error
} finally {
if (fis == null) {
// This bypasses cleanup code
throw new FileNotFoundException();
}
if (stmt != null) {
try {
// Not executed if the exception is thrown
stmt.close();
}
catch (SQLException e) {
log(e);
}
}
}
}
The call to stmt.close() is bypassed when the FileNotFoundException is thrown.
Note
Why are you checking for null using a NullPointerException instead of a basic if-else? There is rarely ever a valid reason to catch a NullPointerException. Just do:
try (InputStream resource = ErrorResource.classLoader.getResourceAsStream(fileName)) {
if (resource == null) {
// TODO Throw your exception here
}
return new String(resource.readAllBytes(), StandardCharsets.UTF_8);
}
It might also help to improve the error message by telling the exact reason that the resource could not be found.
Consider the following code, which is loosely based on yours:
String throwing(InputStream inputStream) throws IOException {
try (InputStream resource = inputStream) {
return "good";
} catch (NullPointerException n) {
return "bad";
}
}
You see, no exceptions thrown here. Still, you cannot remove the throws IOException bit – how’s that? Well, InputStream#close() can throw it, and it will be in the implicit finally block that the try-with-resources statement created. I guess there’s not much you can do about it, it looks like a Fortify false positive.
Beyond the misleading message from your tool, there is actually is poor error handling in your code, for multiple of reasons:
catching NPE is really bad practice. Either it is a bug (something that is null and shouldn't), or your code is missing a check if (whatever == null) and the corresponding code to deal with that expected situation
assuming that this NPE has exactly that meaning that you express in your new Exception is well, just guessing
In other words: without further information, it is not clear what exactly your tool complains about. But: one doesn't need a tool to understand: this is poor error handling.
Beyond that, such tools typically give some sort of information about their warnings. Meaning: there might be an "error id" coming with that warning, and you should be able to look up that "error id" in the documentation of your tool for further explanations.

Properly closing JDBC connection objects

As far as I understood, closing the connection objects in finally block is the best practice. However, if rs.close() / ps.close() throws an exception at the finally block, it won't execute the conn.close(). Therefore I used to close connections at two positions (as in sample provided), once directly after use, and secondly additionally in a finally-block using a check for null. But some consider block 1 as redundant code. Is it really redundant or is there proper way to address this issue without closing the connection in two places?
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = dataSource.getConnection(); // geting the connection object
ps = connection.prepareStatement(INSERT_QUERY);
rs = ps.executeQuery();
// some logic here ...
// ---- block 1 ----
ps.close()
ps = null;
rs.close();
rs = null;
conn.close();
conn = null;
// ---- end block 1 ----
} catch (SQLException e) {
// exception handling ...
} finally {
closeQuietly(conn, ps, rs);
}
private void closeQuietly(Connection connection, PreparedStatement ps, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {}
}
}
is there proper way to address this issue without closing the connection in two places?
Yes:
try (Connection conn = dataSource.getConnection(); // geting the connection object
Prepared Statement ps = connection.prepareStatement(INSERT_QUERY);
ResultSet rs = ps.executeQuery();) {
// ...
}
This is the 'try-with-resources' syntax. Everything declared inside the () after the try is guaranteed to be closed.
Yes, it would be called twice if everything goes fine with your code. That's the reason, people prefer to close any sort of connections (jdbc, stream etc) in the finally block.
As you know, The finally block gets executed whether program executed correctly or not.
So, I would recommend that you should not closing code after the use.
Jitendra
Block 1 is indeed redundant, as closeQuietly will always run due to the finally block.
closeQuietly does the right thing:
As each resource is surrounded by its own try-catch block, the code to cleanup the connection will run even if the block closing the statement or resultset throw exceptions: Those exceptions will be caught and ignored by their try-catch blocks.

What is the best way to create Statement and ResultSet in java

Should I initialize Statement and ResultSet in try-with-resources Statement or just initialize in try block and close Statement and ResultSet in finally block.
I need to understand the best way to implement this according to the best practices
try-with-resources Statement
try(Connection connection = DriverManager.getConnection("url");
Statement st = connection.createStatement();
ResultSet rs = st.executeQuery("query")){
} catch (SQLException e) {
e.printStackTrace();
}
or try-catch with finally
Statement st = null;
ResultSet rs = null;
try(Connection connection = DriverManager.getConnection("url"))
{
st = connection.createStatement();
rs = st.executeQuery("query");
} catch (SQLException e) {
e.printStackTrace();
}
finally {
try {
rs.close();
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
I believe that most of the time less code is more clean code.Secondly readability does matter if you are working with a team and your team member can not read your code properly than it's definitely your fault.
In first case its look quite simple and easily understandable for the programmer who have worked with Java7 and removes the boiler plate code of closing the resources.In the second case you first initialized with null and have finally block with try-close-catch session.It is always better to go with the clean code which is the first one and note one more thing,
In a try-with-resources statement, any catch or finally block is run
after the resources declared have been closed.
Problem with try-with-resource is you can not use the resources out of the scope of try it will be limited to try block while that's not the case in your second part.

Order in closing resources

Should I close the statement before the connection? And the resultset before the statement?
Or is it all the other way around?
Connection conn = null;
Statement st = null;
Resultset rs = null;
try {
// Do stuff
} catch (SQLException e) {
// Do stuff
}
finally {
if (rs != null) rs.close();
if (st != null) st.close();
if (conn != null) conn.close();
}
Or
Connection conn = null;
Statement st = null;
Resultset rs = null;
try {
// Do stuff
} catch (SQLException e) {
// Do stuff
}
finally {
if (conn != null) conn.close();
if (st != null) st.close();
if (rs != null) rs.close();
}
Close the result set, then the statement, then the connection.
In other words, close everything down on a last-in-first-out basis.
You should close the resources in the reverse of the order you opened (as if these resources are on a stack).
With Java 7 try-with-resources, the ideal way is:
try (
Connection conn = somethingThatGetsAConnection();
Statement st = conn.createStatement();
Resultset rs = st.executeQuery("SELECT something");
) {
// Do stuff
} catch (SQLException e) {
// Do stuff
}
And Java will take care of it for you, and it will close the resource in the reverse order. See also the Oracle tutorial on try-with-resources:
Note that the 'close' methods of resources are called in the opposite order of their creation.
You can find a more in-depth look at try-with-resources in the article Better Resource Management with Java SE 7: Beyond Syntactic Sugar
The Java Language Specification for Java 7 mentions in section 14.20.3:
Resources are initialized in left-to-right order. If a resource fails to initialize (that is, its initializer expression throws an exception), then all resources initialized so far by the try-with-resources statement are closed. If all resources initialize successfully, the try block executes as normal and then all non-null resources of the try-with-resources statement are closed.
Resources are closed in the reverse order from that in which they were initialized. A resource is closed only if it initialized to a non-null value. An exception from the closing of one resource does not prevent the closing of other resources.
This can also be seen as a clear indication that the Java language designers consider closing resources in the reverse order they where allocated the norm.
ResultSet, Statement and then the Connection. The golden rule to JDBC connections and statements is to close in the reverse order of initiation or opening. In addition, the ResultSet is dependant on the execution of the Statement and the Statement is dependant on the Connection instance. Hence, the closing should occur in that order (ResultSet, Statement, Connection).
The first example is the right way. The problem with any other order is that closing a Statement will automatically close any underlying ResultSet as well (and same may happen for a Connection) - so you need to close the one lowest in the hierarchy first.
The close() methods may throw a SQLException, as #aubin pointed out. One easy solution to this problem is to use DBUtils closeQuietly() method for closing them - then you don't even need to null-check!
To solve this with minimal effort, try using Java 7's new A.R.M. (Automatic Resource Management) Blocks, also known as Try-With-Resources.
try (Connection conn = null, Statement st = null, ResultSet rs = null){
// Do stuff
} catch (SQLException e) {
// Do stuff
}
No ugly Finally or worrying about proper order, Java takes care of it for you.
Some more info regarding ARM/Try-With-Resources Blocks: http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
Conclusion: the order does not really matter as long as you close them individually.
From the official API specification on close() on class Connection, Statement and ResultSet:
For already closed resources, close() is a no-op:
Calling the method close on a Connection object that is already closed is a no-op.
Calling the method close on a Statement object that is already closed has no effect.
Calling the method close on a ResultSet object that is already closed is a no-op.
Closing a resource of "higher order" closes their "derived" resources:
[Connection.close()] Releases this Connection object's database and JDBC resources immediately instead of waiting for them to be automatically reeased.
[Statement.close()] Note:When a Statement object is closed, its current ResultSet object, if one exists, is also closed.
You can try the following code to see if closing Connection also closes the other two resources:
// url, username, password and sql pre-defined
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try
{
conn = DriverManager.getConnection(url, username, password);
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
}
catch (SQLException e) { e.printStackTrace(); }
finally
{
if (conn != null)
{
System.out.println("conn is not null and I'm about to close it");
try
{
conn.close();
System.out.println(stmt != null && stmt.isClosed() ?
"stmt is also closed" : "stmt is alive");
System.out.println(rs != null && rs.isClosed() ?
"rs is also closed" : "rs is alive");
}
catch (SQLException e) { e.printStackTrace(); }
}
}
Hence, say if we close them in this FIFO order: Connection > Statement > ResultSet:
finally
{
if (conn != null)
{
try { conn.close(); }
catch (SQLException e) { e.printStackTrace(); }
}
if (stmt != null)
{
try { stmt.close(); }
catch (SQLException e) { e.printStackTrace(); }
}
if (rs != null)
{
try { rs.close(); }
catch (SQLException e) { e.printStackTrace(); }
}
}
If a "higher order" resource is successfully closed, its "derived" resources should've been closed as well
Calling close() on these already closed resources is a no-op but is fine as no exceptions are thrown
If failed to be closed, its "derived" resources still have a chance to be closed
And you can also tell the similiar story for any other arrangements.

Catch Exception in finally { } ? Must?

I feel puzzle ...
I write a small routine in .jsp. Finally, ResultSet, Statement and Connection are required to be closed. I also write the closing codes in finally { }, but when the page is run, it return error that I didn't catch exception ...
I read some forum. Other people didn't catch any exception in finally { }
Any Hint ?
Sounds like you have the old problem of needing to close() in a finally block but close() throws an exception itself. Try somethig like the following...
ResultSet rs;
try {
// do various stuff
rs = ...;
} finally {
try {
if (rs != null) rs.close();
} catch (SQLException e) {
// do something with exception
}
}
You must catch exceptions in the code finally block. As you must catch exceptions in the catch block. Nested try/catches are a regular thing (albeit ugly).
One important note here is that you could have the exceptions that occur in finally declared in the throws clause of the method. However that would lead to the exception in finally overriding the original exception, which is lost. And you will see, for example, a NullPointerException, rather than FileNotFoundException.
By the way, avoid having code in the JSP file. Place it in a servlet.
finally{} doesn't do any exception catching. A finally{} block exists to make sure that certain code is run, no matter whether the try{} block reached its natural end or if it's jumping temporarily to the finally{} because an exception happened and that finally{} block was along the way. But after the finally{} finishes, the exception goes about its merry business, cavorting its way up the stack and cheerfully crashing your program.
If you want to actually catch the exception and stop it from unwinding the stack further, use catch(){}. But don't use catch blindly- catching an exception you don't actually know how to recover from is much worse than crashing, because now your program isn't working correctly and you don't have an exception stack trace telling you why.
Your ResultSet, Statement, and Connection almost certainly did get closed. And then the exception continued happening and crashed your program anyway, because that had nothing to do with your ResultSet, Statement, and Connection.
What was the actual exception?
Maybe I'm getting old, but what's wrong with catching exceptions in the catch block?
It helps if you say what is in your try block. You are probably not catching appropriate exception or your code in finally throws exception.
It is OK to have finally without catch.
try {
//do some work
}
finally {
//check of state and do clean up. You would have reached here via multiple branches.
}
It more appropriate to catch specific exceptions using catch and then handle specific cleanup there. Use finally for any code that must get executed even when exception happen.
try {
//do some work
}
catch ( RecoverableException1 re1) {
//cleanup
}
catch ( RecoverableException2 re2) {
//cleanup
}
finally {
//check of state and do clean up. You would have reached here via multiple branches.
}
finally{
try{
resultSet.close();
}catch(E e){
}finally{
try{
statement.close();
}catch(E e){
}finally{
conn.close();
}
}
}

Categories