I have recently moved to a project where I am encountering a lot of code of this nature - (This is using the jdbc postgres driver)
try {
Connection conn = pool.getAConnection(); //home-grown conn pool
PreparedStatement ps = ..;
ResultSet rs = ..;
rs = ps.executeQuery();
...
} catch (SQLException se) {
conn.close();
} finally {
if (stmt != null) stmt.close();
if (rs != null) rs.close();
}
Apparently this code has been in production for a while, without causing issues.
What I find hard to understand is, in the exception flow, the connection gets closed or returned to the pool first; and then the statement and resultset are attempted to be closed. Does it make sense to execute this after the parent connection object is closed ?
Because of the way the code is structured, connection release has to be done in the exception block. That cannot be changed. That being said, is it okay to leave the stmt.close() and rs.close() in finally after the connection has been released to the pool ?
To clarify further, if my understanding is correct (i.e., statement and resultset must be closed before connection close and not after), I need to repeat some code between the catch and finally. The revised code now looks as below. Can this be simplified ?
try {
...
} catch(Exception ex){
if (rs != null) {
close(rs); rs = null; // close() method impl just calls rs.close() in try-catch block
}
if (ps != null) {
close(ps); ps = null;
}
processException( ex, con); // This method logs and then either closes the connection or releases to pool, depending on some conditions.
con = null;
} finally {
if (rs != null) {
close(rs);
}
if (ps != null) {
close(ps);
}
if (null != con) {
close(con);
}
}
Just for perspective, this code is all over - at least a 100 or so methods ! I would like to simplify this further if possible. Appreciate your feedback.