Finally Closing of JDBC Resources

I love reading Alex’s The Daily WTF and I noticed the recent Finally WTF is relevant to JDBC in an important way. All *good* JDBC developers already know you should close your result sets, statements, and connections (in that order) in a finally block when you are done with them, but do you all know how they should be closed? In particular, while a finally block will be entered under most circumstances, there’s no guarantee every line of code will be executed. Consider the following code I often come across:

Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
     // Do stuff
     ...
} catch (Exception e) {
     // Do exception recovery stuff
     ...
} finally {
     try {
          rs.close();
          stmt.close();
          con.close();
     } catch (Exception e) {  }
}

Now, can you figure out what’s wrong with this code? Imagine if the result set rs is never populated and stays null. The first line of the finally block will throw a NullPointerException, and the stmt.close() and con.close() will never be executed. In other words, your failure to close a result set would lead to a connection never be closed even though it was in a finally block! Sure the code is guaranteed to enter the finally block, but if it fails on the first line, the rest of the code will be skipped. Next, compare this other common but still incorrect solution:

...
} finally {
     try {
          if(rs!=null) {rs.close();}
          if(stmt!=null) {stmt.close();}
          if(con!=null) {con.close();}
     } catch (Exception e) {  }
}

This solution is a little safer in that it avoids NullPointerExceptions, but it’s equally as useless as the first solution in that there are a number of reasons why the first line of code could still fail, for example if the result set is already closed. This solution actually worries me the most because clearly the developer went through the trouble of setting up the finally block and null pointer catches, but failed to fully understand how a finally block works. Now, I present a superior solution:

...
} finally {
     try {rs.close();} catch (Exception e) {}
     try {stmt.close();} catch (Exception e) {}
     try {con.close();} catch (Exception e) {}
}

Now, is this solution safe? See that if rs or stmt fail to close, the call to con.close() will still be executed. Granted you could get fancy by adding logic to handle/log the exceptions or even catch Throwable (although catching Throwable’s never a good practice), but that’s a bit overkill. You could also nest your finally block with more finally blocks (just add finally block to the rs’s try/catch and put the rest inside it… and so on) although I tend to prefer this solution since it’s more readable.

Lastly, you could make helper methods for closing the the objects to make the code easier to work with such as:

...
} finally {
     DBUtil.close(rs);
     DBUtil.close(stmt);
     DBUtil.close(con);
}

Where the try/catch is inside the helper methods. Keep in mind this last solution isn’t really different from the previous solution, just a code management improvement.