JDBC のログとりメモ

– close() するのは PreparedStatement#close() でなく ResultSet#close() でもなく、絶対に Connection でなければならない。
– ログ情報には PreparedStatement#toString() がよさげ(少なくとも com.mysql.jdbc では)。
理由は、ログのための利便性から。SQLException がどのクエリでエラーになったかを残してくれないので、 PreparedStatement インスタンスがクエリ周りの情報をきっちり保持してくれていれば、toString() でログにどのクエリ文を実行したかが残せる。しかし、PreparedStatement#close() は DB 接続を閉じる仕様とは限らないため、Connection#close() を呼ぶ必要がある。PreparedStatement#close() だけにしたらプールがあふれ、思わぬ場所で DB 接続が開くのをずっと待ち続けることになってしまった。
– 例:

boolean isExist(int id){
    PreparedStatement ps = null;
    try{
        final Connection con = getConnection();
        try{
            ps = con.prepareStatement(“SELECT id FROM list WHERE id = ? LIMIT 1”);
            ps.setInt(1, id);
            return ps.executeQuery().next();
        }finally{
            con.close();
        }
    }catch(SQLException e){
        log(“Query error [“+ps+”]”, e); // void log(String, Throwable); とする
        return false;
    }
}