Michael Laffargue
Michael Laffargue

Reputation: 10314

Java 1.6 java.sql try/catch/finally crazy coding

I'm currently creating a lot of classes that will access database using a connection pool. So I get a connection, create a statement and get the result set. (I can't use Java 1.7 and the fantastic Automatic Resource Management) When finishing my method I must finish with a finally block:

        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException sqle) {
                logger.error("Couldn't close result set", sqle);
            }
        }
        if (st != null) {
            try {
                st.close();
            } catch (SQLException sqle) {
                logger.error("Couldn't close statement", sqle);
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException sqle) {
                logger.error("Couldn't close connection", sqle);
            }
        }

I'm already seeing the nightmare it will be for XX classes having 4/5 methods each.

Would it be good practice to make an helper class which would got a special close method for each object type like :

public static void closeResource(Connection connection) {
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException sqle) {
                logger.error("Couldn't close connection", sqle);
            }
        }

And then just doing my usual finally with xx.close(connection);xx.close(statement);xx.close(rs);

Or in the same thinking (I know at this point I'll shock some people as I myself find that a bit ackward), having a method like public static void closeResources(Object... obj) {} with an awful list of instanceof ?

Or in your experience, coding the whole thing everywhere is better ?

Upvotes: 1

Views: 2089

Answers (4)

Mister Smith
Mister Smith

Reputation: 28199

You could also exploit the fact that for every class you want to close, the close method has no args, and make a reflective helper method like this:

    public static final void tryClose(Object o){
        if(o != null){
            Method[] m = o.getClass().getMethods();
            for (Method method : m) {
                if("close".equals(method.getName())){
                    if(!method.isAccessible()) method.setAccessible(true);
                    try {
                        method.invoke(o);
                    } catch (Exception e) {
                        System.err.println(e);
                    }
                    break;
                }
            }
        }       
    }

EDIT: Tested with FileWriter, works fine in my machine.

Upvotes: 0

lxbndr
lxbndr

Reputation: 2208

Just one more example. Suitable for simple small projects.

Object doRequest() throws SQLException {

    PreparedStatement ps = ... // initialize statement
    try {
        ResultSet rs = ps.executeQuery();
        try {

           // use ResultSet
           return someResult;

        } finally {
           rs.close();
        } 
    } finally {
        ps.close();
    }

}

Although it is not pretends to be complete solution (many nested try-finally are quite unreadable), there are several advantages:

  • Method itself not deals with exception handling. Often only caller may decide what to do with exception.
  • As follows, method always returns correct result or throws exception. No magic "error values" required.
  • Resources closed only if they were initialized. No need to check for null berode close().

Upvotes: 1

chburd
chburd

Reputation: 4159

Use Apache commons project : http://commons.apache.org/dbutils/apidocs/org/apache/commons/dbutils/DbUtils.html

DbUtils.closeQuietly() is probably what you need

Upvotes: 2

adarshr
adarshr

Reputation: 62623

Use overloading.

private void close(ResultSet rSet) throws SQLException {
    if (rSet != null) {
        rSet.close();
    }
}

private void close(Statement statement) throws SQLException {
    if (statement != null) {
        statement.close();
    }
}

private void close(Connection conn) throws SQLException {
    if (conn != null) {
        conn.close();
    }
}

Usage will be much cleaner now:

try {
    // do db stuff
} catch (Exception e) {
    logger.error("log it", e);
} finally {
    close(rs);
    close(cs);
    close(conn);
}

Upvotes: 2

Related Questions