I have often come across situations like :-
try{ ... stmts ... } catch(Exception ex) { ... stmts ... } finally { connection.close // throws an exception }
which still needs a try - catch block inside finally.
What is the best practice to overcome this?
When catch and finally block both return value, method will ultimately return value returned by finally block irrespective of value returned by catch block.
Yes, we can write a return statement of the method in catch and finally block.
catch statement is comprised of a try block and either a catch block, a finally block, or both. The code in the try block is executed first, and if it throws an exception, the code in the catch block will be executed. The code in the finally block will always be executed before control flow exits the entire construct.
Try block contains the code that might throw an exception. Catch block contains the exception handler for exceptions in the try block. The finally block contains the critical code that will execute regardless of whether the exception has occurred or not.
Write a SQLUtils
class that contains static closeQuietly
methods that catch and log such exceptions, then use as appropriate.
You'll end up with something that reads like this:
public class SQLUtils { private static Log log = LogFactory.getLog(SQLUtils.class); public static void closeQuietly(Connection connection) { try { if (connection != null) { connection.close(); } } catch (SQLExcetpion e) { log.error("An error occurred closing connection.", e); } } public static void closeQuietly(Statement statement) { try { if (statement!= null) { statement.close(); } } catch (SQLExcetpion e) { log.error("An error occurred closing statement.", e); } } public static void closeQuietly(ResultSet resultSet) { try { if (resultSet!= null) { resultSet.close(); } } catch (SQLExcetpion e) { log.error("An error occurred closing result set.", e); } } }
And your client code will be something like:
Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { connection = getConnection(); statement = connection.prepareStatement(...); resultSet = statement.executeQuery(); ... } finally { SQLUtils.closeQuietly(resultSet); SQLUtils.closeQuietly(statment); SQLUtils.closeQuietly(connection); }
Update: since Java 7, the various JDBC interfaces extend java.lang.AutoCloseable
and while the above code answers the original question, if you're writing code directly against the JDBC API, it can now be structured:
try ( Connection connection = getConnection(); PreparedStatement statement = connection.prepareStatement(...); ResultSet resultSet = statement.executeQuery() ) { ... }
As others have mentioned, a static closeQuietly
utility is the way to go. One thing to add - if you are in the world of java.io
rather than java.sql
then there is a useful interface for exactly this purpose - java.io.Closeable
All the data sources and sinks in java.io
implement this interface - all streams, channels, writers and readers. That way you can create a single utility to cope with the same "exception on close()" issue without requiring many overloaded versions.
e.g.
public class IoUtils { public static closeQuietly (Closeable closeable) { try { closeable.close(); } catch (IOException logAndContinue) { ... } } }
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