トランザクションの処理がおかしかったが、
複雑な処理なため、commit/rollback がどこで行われているのかを
追うのが大変。こんなときに、DbUtils の ProxyFactory が役立った。
java.sql.Connection をラップして、commit/rollback が呼ばれた時にコンソールにメッセージ出すだけだけど。

package dcc.database;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.sql.Connection;

import org.apache.commons.dbutils.ProxyFactory;

public class ConnectionWrapper implements InvocationHandler {
private static final ProxyFactory factory = ProxyFactory.instance();

public static Connection wrap(Connection conn) {
return factory.createConnection(new ConnectionWrapper(conn));
}

private final Connection conn;

public ConnectionWrapper(Connection conn) {
super();
this.conn = conn;
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

Object result = method.invoke(this.conn, args);

if(method.getName().equals("commit")) {
System.out.println("COMMIT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
} else if(method.getName().equals("rollback")) {
System.out.println("ROLLBACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}

return result;
}
}