views:

382

answers:

5

I've too many methods that repeatedly do something like

Statement stmt = null;
ResultSet rstmt = null;
try {
    stmt = conn.createStatement();
    rstmt = stmt.executeQuery(...);
    while (rstmt.next()) {
     //handle rows
    }


} catch (SQLException e) {
    //handle errors

} finally {
    try {rstmt.close();} catch (SQLException ex) {}
    try {stmt.close();} catch (SQLException ex) {}
}

This setup/teardown/cleanup of statements and resultsets is repetive and hides the interesting pieces of code.

Is there any pattern or idiom for handling this(without introducing any external framework) ?

+4  A: 

You want the Execute Around idiom.

You may want to ask 'What is the "Execute Around" idiom?'.

(And if you like ASCII diagrams: my weblog on 'Factoring out exception handling')

Tom Hawtin - tackline
+9  A: 

Have a look at SimpleJDBCTemplate in Spring Framework. This does exactly what you want.

If you don't want to introduce an external framework then just use it for some inspiration to implement your own.

Mark
+1 from me. This is exactly the right thing to do. Either using Spring as inspiration or incorporating it into your project will be beneficial.
duffymo
In addition to hiding this messy setup\teardown code, Spring will improve the exception handling in 2 ways:1) it will handle the SQLException and 'regurgitate' it as something more meaningful2) the exception that is 'regurgitated' will be unchecked, so you don't have to catch or throw anything.
javamonkey79
+1. LOVE the way jdbc is handled with spring.
matt b
absolutely agree
Paul McKenzie
+1  A: 

You should reconsider using Java persistence managers like iBatis and Hibernate. These automate a lot of the boilerplate away. I've been using iBatis, where the SQL statements are all neatly packaged and named in XML files, and the code volume has to be about 25% of a raw JDBC approach. You could gradually refactor your system to use iBatis.

Jim Ferrans
+4  A: 

you can create a method that receives the SQL query and an object to handle the ResultSet. for example:

private void executeSql(String sql, ResultSetHandler handler) {
  Statement stmt = null;
  ResultSet rstmt = null;
  try {
    stmt = conn.createStatement();
    rstmt = stmt.executeQuery(sql);
    while (rstmt.next()) {
      handler.handle(rstmt);
    }
  }
  catch (SQLException e) {
    //handle errors
  }
  finally {
    try {rstmt.close();} catch (SQLException ex) {}
    try {stmt.close();} catch (SQLException ex) {}
  }
}

with ResultSetHandler being an interface:

public interface ResultSetHandler {
  void handle(ResultSet rs) throws SQLException;
}

and you can create an object of an anonymous class implementing that interface, so it won't clutter too much.

cd1
Probably want to make that interface method throw at least SQLException.
Tom Hawtin - tackline
good idea, Tom.
cd1
A: 

Although it does not eliminate the set-up and tear-down logic, I often prefer this style for making JDBC interactions more pleasant:

Statement statement = connection.createStatement();
try {
    ResultSet results = statement.executeQuery(...);
    try {
        while (results.next()) {
            //handle rows
        }
    } finally {
        results.close();
    }
} finally {
    statement.close();
}

By nesting the try blocks, you automatically ensure that both results and statement will have their close() methods called without resorting to the try/catch statements in your finally block. As well, by starting the try blocks immediately after acquiring your objects, you don't need to worry about checking for null values (unless, of course, connection.createStatement() or statement.executeQuery(...) return null - In that case, you have bigger issues).

Adam Paynter
Doesn't this code strike you as, well ..., ugly?
Paul McKenzie
I suppose beauty is in the eye of the beholder. I personally find this form more "appealing" than the form presented in the question.
Adam Paynter