1

JDBC for PostgreSQL を使用して実行しようとしているかなり長いトランザクションがあります。JDBC ではCOMMITandROLLBACKを使用できないため、目的の動作を Java コードで実装しようとしています...

try {
    con = DriverManager.getConnection(url, user, password);

    con.setAutoCommit(false);
    Statement st = con.createStatement();
    st.execute(myHugeTransaction);

    con.commit();
} catch (SQLException ex) {
    try {
        con.rollback();
    } catch (SQLException ex1) {
        // log...
    }
    // log...
}

小さなステートメントの場合、これはかなりうまく機能しますが、1 つのトランザクションに約 10K のステートメントがある大きなステートメントの場合、これは次のcon.commit行で失敗します。

org.postgresql.util.PSQLException: ERROR: kind mismatch among backends. Possible last query was: "COMMIT" kind details are: 0[C] 1[N: there is no transaction in progress]

面白いことに、SQL 警告をキャッチするとst.getWarnings();、送信したスクリプト全体をデータベースが実際に処理していることがわかりますが、コミットに関してはすべて失敗します。

ところで、トランザクションはまったく問題ありません。その正確なコピーをファイルに書き込み、それをpgAdminにコピーすることでエラーなしで実行できます。あなたがそれについて私を助けてくれることを願っています.私は何時間も検索してテストしてきました...

編集

よく分からなかったので、2点質問させてください。

  1. への 1 回の呼び出しで複数のステートメントを実行できますStatement.execute()か?
  2. そうでない場合、JDBC を使用して複数のステートメントでスクリプトを実行する正しい方法は何ですか (解析して単一のステートメントに分割する必要はありません)。
4

1 に答える 1

0

正直なところ、これが SQL スクリプトである場合は、psql にシェル エスケープを実行する方が適切です。これが、これを処理する最善の方法です。一般に、SQL コードを解析してデータベースに対して実行しようとする人々から、あまりにも多くの不愉快な驚きを受けてきました。このように狂気は横たわっています。

「より小さなスクリプト」と言うと、データベースをセットアップするようなことをしていると結論付けられます(またはデータベースをアップグレードしますが、クエリがないため可能性は低くなります)。シェル エスケープを通じて psql を使用し、振り返らないでください。それが本当に最善の方法です。

必要に応じて、明示的な BEGIN と COMMIT をスクリプトに追加してみてください。

トランザクションを暗黙的にコミットしているように見える理由がわかりません。自動コミットを適切にオフに設定しました。コードに明らかな問題はありません。古いまたはバグのある JDBC ドライバーを使用している可能性はありますか? そうでない場合は、PostgreSQL JDBC ドライバー プロジェクトにバグ レポートを提出することをお勧めします。

于 2013-03-17T13:00:43.737 に答える