2012-03-28 37 views
0

1つの関数でいくつかのテーブルを変更する必要があります。彼らはすべて成功しなければならない、またはすべて失敗する必要があります。 1つの操作が失敗した場合は、それらの操作がすべて失敗するようにします。私は以下を持っています:いつjava.sql.Connection.rollback()を呼び出す必要がありますか?

私はこのプロセス中に何か問題が起こった場合にrollback()を呼び出す必要があるのだろうかと思います。

その他の情報:接続プールを使用しています。上記のサンプルでは、​​最終的なステートメントも使用して各PreparedStatementを閉じるようにしています。簡潔にするために残しておきます。

あなたは

答えて

1

あなたはrollback()を呼び出す必要はありませんありがとうございました。 commit()を完了せずに接続が終了すると、ロールバックされます。

connnullのいずれかを設定する必要はありません。 connが初期化された後にtryブロックが開始されるため(...はnullに評価できないと仮定します)、!= nullfinallyには必要ありません。

+0

[OK]をそうでもアップデートして、そのCONNを反映する例がnullの場合も、更新Iロールバック()を呼び出す必要はありませんか?ありがとう – user291701

+0

正しいです、あなたはロールバックを呼び出す必要はありません。前の例では、 'conn'が' try'の前に初期化されました。 –

+0

これは単に真実ではありません。変更をロールバックするには、接続でロールバックを呼び出す必要があります。自動的にロールバックされることはありません。私の答えを参照してくださいが、コミットを呼び出す前に例外をスローすることによって自分自身でテストするのは簡単です。 –

0

"コミット"を呼び出すと、トランザクションがコミットされます。複数の挿入/更新文があり、そのうちの1つが失敗した場合、コミットするとデータベースにコミットするのに失敗しなかった挿入/更新が行われます。だから、他のステートメントをdbにコミットさせたくない場合は、ロールバックを呼び出す必要があります。 autocommitをfalseに設定して本質的に何をしているのかは、複数のステートメントをコミットまたはロールバックすることです。それ以外の場合、個々のステートメントは自動的にコミットされます。

+0

私の答えを明確にするために、これは複数の記述があることを前提としています。 1つのステートメントしかない例では、自動的にロールバックされます。しかし、Javaコードで複数のステートメントが呼び出されている場合は、ロールバックしたいと考えています。 – DavidB

+0

複数のステートメントがあることを示すために更新されました(変数はうまく再利用されます)。ロールバックはまだ必要ですか?おかげで – user291701

+0

あなたは防衛的にコードする必要があります。上記のコードは単一の接続で動作し、明示的にロールバックを呼び出す必要はありません。しかし、接続プールがある環境にそのコードをドロップすると、プール内で接続が頻繁に閉じられないため、他のトランザクションが同じ接続を再利用するため、奇妙な動作に縛られます。個人的には、パフォーマンスヒット(ロールバックは高価です)を引き起こしていると明確に識別できない限り、常にロールバックを使用し、作業している環境のトランザクション動作を完全に理解しています。 – DavidB

0

はいいずれかのステートメントが失敗した場合、またはコミットを呼び出す前に例外を検出した場合は、ロールバックを呼び出す必要があります。これは古い投稿ですが、受け入れられる答えは間違っています。コミットする前に例外をスローし、手動でロールバックしなければ挿入がデータベースに残っていることを確認することで、自分で試すことができます。ドキュメントから

JDBCドキュメント https://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html#call_rollback

例正しい使用

public void updateCoffeeSales(HashMap<String, Integer> salesForWeek) 
    throws SQLException { 

    PreparedStatement updateSales = null; 
    PreparedStatement updateTotal = null; 

    String updateString = 
     "update " + dbName + ".COFFEES " + 
     "set SALES = ? where COF_NAME = ?"; 

    String updateStatement = 
     "update " + dbName + ".COFFEES " + 
     "set TOTAL = TOTAL + ? " + 
     "where COF_NAME = ?"; 

    try { 
     con.setAutoCommit(false); 
     updateSales = con.prepareStatement(updateString); 
     updateTotal = con.prepareStatement(updateStatement); 

     for (Map.Entry<String, Integer> e : salesForWeek.entrySet()) { 
      updateSales.setInt(1, e.getValue().intValue()); 
      updateSales.setString(2, e.getKey()); 
      updateSales.executeUpdate(); 
      updateTotal.setInt(1, e.getValue().intValue()); 
      updateTotal.setString(2, e.getKey()); 
      updateTotal.executeUpdate(); 
      con.commit(); 
     } 
    } catch (SQLException e) { 
     JDBCTutorialUtilities.printSQLException(e); 
     if (con != null) { 
      try { 
       System.err.print("Transaction is being rolled back"); 
       con.rollback(); 
      } catch(SQLException excep) { 
       JDBCTutorialUtilities.printSQLException(excep); 
      } 
     } 
    } finally { 
     if (updateSales != null) { 
      updateSales.close(); 
     } 
     if (updateTotal != null) { 
      updateTotal.close(); 
     } 
     con.setAutoCommit(true); 
    } 
} 
関連する問題