原因が分かりました。
コネクションプールを使用しているWebアプリだったのですが、
吐き出されるSQLクエリのログを見てみると

Connection conn = pool.getConnection(); // poolからコネクション取得
conn.setAutoCommit(false); // (1) begin;
/* いろいろな処理 */
conn.commit(); // (2) commit; begin;
conn.setAutoCommit(true); // (3) end;
conn.close() // poolにコネクションを戻す

最初は(3)の文が抜けていたため、ずーっと
あるコネクションがpoolの中でトランザクション中の
状態になっていたようです。

ところで(2)の conn.commit() が「commit; begin;」という
SQLクエリを発行するのが JDBC の一般的な仕様なのでしょうか?
ここが commit; だけなら何も苦労しなかったのに・・・