3

私は理解できない問題に遭遇しました。

次の SQL コード スニペットでは、テーブルに複数の行を挿入しています。例外で行が追加されないことが重要です。

コードは意図したとおりに機能しますが、ロールバック部分が削除されると、connection.commit(); であっても例外でいくつかの行が追加されます。呼び出されることはありません。何故ですか?

私の懸念は次のとおりです。バッチ挿入の呼び出し中にアプリケーションがオペレーティング システムによって強制終了され、それによってロールバック部分が呼び出されない場合はどうなりますか。私のテストでは、その場合は何も挿入されていないことが示されています。しかし、ロールバック部分が削除された場合、例外でいくつかの行が挿入される理由にまだつまずいています。

これに関するヒントはありますか?

    Connection connection = null;
    PreparedStatement stmt = null;

    try {
        connection = DBConnectionFactory.getInstance().getConnection(JDNI);
        connection.setAutoCommit(false);

        stmt = connection.prepareStatement(
                "INSERT INTO " + TABLE_PREFIX + TABLE_OUTBOX + "...");

        // add multiple statements

        stmt.executeBatch();

        connection.commit();

    } catch (Exception ex) {
        try {
            log.debug(ex);
            log.debug("rolling back insert message batch");
            connection.rollback();
            log.debug("rollback success");
        } catch(Exception e) {
            log.debug("unable to rollback", e);
        }
        throw new TranquilityException("could not insert endpoints!!", ex);
    } finally {
        if (stmt != null) {
            try {
                stmt.close();
            } catch (Exception ex) {
                log.warn("Could not close sql statement", ex);
            }
        }
        if (connection != null) {
            try {
                connection.setAutoCommit(true);
                connection.close();
            } catch (Exception ex) {
                log.error("Could not close sql connection", ex);
            }
        }
    }
}
4

1 に答える 1

0

これが起こる理由は 2 つあります。

  • 1 つ目は、接続プールを使用しているように見えることです。この場合、接続が再利用されます。コミットされていないトランザクションを含む接続をプールに戻し、その接続が後で別のメソッドによってチェックアウトされた場合、その後のメソッドがコミットされたときにトランザクションがコミットされる可能性があります。

  • 2 つ目 (そしてより可能性が高い) は、finally ブロックで、connection.setAutoCommit(true); を設定していることです。メソッドが完了すると、接続内のすべてがフラッシュされます。接続プールに対してこれを行う必要があることはわかっていますが、これを行う前に、接続が完了状態であることを確認する必要があります。

于 2012-10-03T12:11:15.003 に答える