テーブルに挿入を行うJavaとPostgreSQLを使用してこのエラーが発生しました。このエラーを再現する方法を説明します:
org.postgresql.util.PSQLException: ERROR:
current transaction is aborted, commands ignored until end of transaction block
概要:
このエラーが発生する理由は、トランザクションを入力し、SQLクエリの1つが失敗し、その失敗を食い止めて無視したためです。しかし、それだけでは不十分でした。次に、同じ接続を使用し、同じトランザクションを使用して別のクエリを実行しました。壊れたトランザクションを使用して追加の作業を行っているため、2番目の正しく形成されたクエリで例外がスローされます。 PostgreSQLはデフォルトで、これを実行できなくなります。
使用しているもの: PostgreSQL 9.1.6 on x86_64-redhat-linux-gnu, compiled by gcc (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2), 64-bit".
私のPostgreSQLドライバーは次のとおりです: postgresql-9.2-1000.jdbc4.jar
Javaバージョンの使用: Java 1.7
例外を説明するためのテーブル作成ステートメントは次のとおりです:
CREATE TABLE moobar
(
myval INT
);
Javaプログラムによりエラーが発生します:
public void postgresql_insert()
{
try
{
connection.setAutoCommit(false); //start of transaction.
Statement statement = connection.createStatement();
System.out.println("start doing statement.execute");
statement.execute(
"insert into moobar values(" +
"'this SQL statement fails, and it " +
"is gobbled up by the catch, okfine'); ");
//The above line throws an exception because we try to cram
//A string into an Int. I Expect this, what happens is we gobble
//the Exception and ignore it like nothing is wrong.
//But remember, we are in a TRANSACTION! so keep reading.
System.out.println("statement.execute done");
statement.close();
}
catch (SQLException sqle)
{
System.out.println("keep on truckin, keep using " +
"the last connection because what could go wrong?");
}
try{
Statement statement = connection.createStatement();
statement.executeQuery("select * from moobar");
//This SQL is correctly formed, yet it throws the
//'transaction is aborted' SQL Exception, why? Because:
//A. you were in a transaction.
//B. You ran a SQL statement that failed.
//C. You didn't do a rollback or commit on the affected connection.
}
catch (SQLException sqle)
{
sqle.printStackTrace();
}
}
上記のコードは私のためにこの出力を生成します:
start doing statement.execute
keep on truckin, keep using the last connection because what could go wrong?
org.postgresql.util.PSQLException:
ERROR: current transaction is aborted, commands ignored until
end of transaction block
回避策:
いくつかのオプションがあります:
-
最も簡単な解決策:取引をしないでください。
connection.setAutoCommit(false);
を設定しますconnection.setAutoCommit(true);
へ 。失敗したSQLは失敗したSQLステートメントとして無視されるため、これは機能します。必要なSQLステートメントをすべて失敗してもかまいません。PostgreSQLはあなたを止めません。 -
トランザクションを継続しますが、最初のSQLが失敗したことを検出したら、トランザクションをロールバック/再起動またはコミット/再起動します。その後、そのデータベース接続で必要な数のSQLクエリを失敗し続けることができます。
-
SQLステートメントが失敗したときにスローされる例外をキャッチして無視しないでください。その後、プログラムは不正な形式のクエリで停止します。
-
代わりにOracleを入手してください。トランザクション内の接続でクエリに失敗し、その接続を引き続き使用しても、Oracleは例外をスローしません。
このように物事を行うというPostgreSQLの決定を擁護するために...Oracleは 真ん中で柔らかくなり、馬鹿げたことをして見落とすことができます。