自動コミット設定とロールバックの使い方

自動コミット設定について

プログラム例

package dbsample;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TransactionExample {

    public static void main(String[] args) {
        // データベース接続情報
        String url = "jdbc:oracle:thin:@localhost:1521:dbName";
        String user = "yourUsername"; // データベースのユーザー名
        String password = "yourPassword"; // データベースのパスワード

        // データベース接続とSQL実行のためのオブジェクト
        Connection conn = null;
        PreparedStatement insertStmt = null;
        PreparedStatement updateStmt = null;

        try {
            // データベースに接続
            conn = DriverManager.getConnection(url, user, password);

            // 自動コミットを無効にして、手動でコミット/ロールバックできるように設定
            conn.setAutoCommit(false);

            // INSERT文の準備
            String insertSql = "INSERT INTO STOCK_TABLE (ID, ITEM_NO, COUNT, UPDATE_TIME) " +
                               "VALUES (?, ?, ?, SYSDATE)";
            insertStmt = conn.prepareStatement(insertSql);
            insertStmt.setInt(1, 101);           // ID(ユニークな値を設定)
            insertStmt.setInt(2, 5);             // ITEM_NO
            insertStmt.setInt(3, 20);            // COUNT

            // UPDATE文の準備
            String updateSql = "UPDATE STOCK_TABLE SET COUNT = COUNT + ? WHERE ITEM_NO = ?";
            updateStmt = conn.prepareStatement(updateSql);
            updateStmt.setInt(1, 5);             // COUNTを増加
            updateStmt.setInt(2, 5);             // 対象のITEM_NO

            // SQL操作を実行
            insertStmt.executeUpdate(); // INSERT操作
            updateStmt.executeUpdate(); // UPDATE操作

            // すべての操作が成功した場合のみコミット
            conn.commit();
            System.out.println("トランザクションが正常にコミットされました。");

        } catch (SQLException e) {
            // エラーが発生した場合はロールバック
            try {
                if (conn != null) {
                    conn.rollback();
                    System.out.println("エラーが発生したため、ロールバックが実行されました。");
                }
            } catch (SQLException rollbackEx) {
                rollbackEx.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            // リソースの解放
            try {
                if (insertStmt != null) insertStmt.close();
                if (updateStmt != null) updateStmt.close();
                if (conn != null) {
                    conn.setAutoCommit(true); // 自動コミットを元に戻す
                    conn.close();
                }
            } catch (SQLException closeEx) {
                closeEx.printStackTrace();
            }
        }
    }
}

基本文法

Javaでは、デフォルトで自動コミット(auto-commit)が有効になっています。自動コミットが有効な場合、各SQL操作(INSERTUPDATEDELETEなど)が実行されるとすぐにデータベースに反映され、個別に確定されます。これに対して自動コミットを無効にすることで、複数のSQL操作をまとめてコミット(確定)することができ、トランザクション単位での処理が可能になります。

自動コミットの設定方法
// 自動コミットを無効にする
conn.setAutoCommit(false);

// 自動コミットを有効にする(デフォルトの設定)
conn.setAutoCommit(true);

上記のコードでconnConnectionオブジェクトです。setAutoCommit(false)を指定すると、自動コミットが無効になり、トランザクションが完了するまで手動でcommitまたはrollbackを行う必要があります。

自動コミットを無効にするメリット

自動コミットを無効にすることで、以下のメリットがあります:

  • 複数のSQL操作をまとめて確定できる
    例えば、INSERTUPDATEを連続して行い、その両方が成功した場合のみコミット(確定)したい場合などに便利です。
  • エラー時に操作を元に戻せる
    トランザクション中にエラーが発生した場合に、ロールバックでデータベースの状態をエラー前に戻すことができます。

ロールバック

基本文法

ロールバックとは、トランザクション中の操作を取り消して、データベースの状態を以前の状態に戻す操作です。エラーが発生した場合や、処理を取り消したい場合に使用します。rollbackを使うには、まず自動コミットを無効にする必要があります。

ロールバックの使用例
try {
    conn.setAutoCommit(false); // 自動コミットを無効にする

    // 複数のSQL操作
    stmt1.executeUpdate(); // INSERT
    stmt2.executeUpdate(); // UPDATE

    conn.commit(); // すべての操作が成功したらコミット(確定)

} catch (SQLException e) {
    conn.rollback(); // エラーが発生したらロールバック
    e.printStackTrace();
} finally {
    conn.setAutoCommit(true); // 最後に自動コミットを有効に戻す
}

上記のコードで、stmt1stmt2はそれぞれ異なるSQL操作(PreparedStatementStatement)です。もしstmt1またはstmt2でエラーが発生した場合、rollback()により全ての操作が元に戻ります。commit()を呼び出すまでは、データベースには反映されません。

ロールバックを使うメリット

  • データの一貫性を保つ
    複数の操作が全て正常に実行された場合のみ、データベースに反映されます。エラーが発生した場合、すべての操作が取り消され、データの一貫性が保たれます。
  • 安全性の向上
    ロールバックにより、データベースの状態が意図せず変更されることを防げます。特に重要なデータ操作では、エラー時に元に戻すことが重要です。

発展的な使い方

部分的なロールバック

特定の処理の前後で明示的にcommit()を呼び出すことで、部分的にロールバックの対象外にすることも可能です。

try {
    conn.setAutoCommit(false);

    stmt1.executeUpdate(); // INSERT
    conn.commit(); // ここで一旦コミットすることでstmt1の結果は確定

    stmt2.executeUpdate(); // UPDATE
    stmt3.executeUpdate(); // DELETE

    conn.commit(); // stmt2とstmt3が成功した場合のみ、再度コミット

} catch (SQLException e) {
    conn.rollback(); // 最後のコミット以降の操作をロールバック
    e.printStackTrace();
}

このコードでは、stmt1が成功すると、そこで一旦commit()を行い、以降の操作を分離することで、stmt2stmt3でエラーが発生してもstmt1の結果は維持されます。


注意点

  • トランザクションの明確な終了
    自動コミットを無効にした場合、明示的にcommit()またはrollback()を行わない限り、トランザクションが終了しません。トランザクションを完了させた後は、再度setAutoCommit(true)で自動コミットを有効にすることが推奨されます。
  • ロールバックが不可な操作
    一部のDDL(テーブル作成や削除)などはロールバックができない場合があります。トランザクション制御は通常、データ操作(INSERTUPDATEDELETE)に対してのみ適用されます。

まとめ

  • 自動コミット設定: デフォルトで有効。複数の操作をまとめて管理したい場合には無効にする。
  • ロールバック: エラーが発生したときに操作を取り消すために使用。データベースの一貫性と安全性を確保できる。
  • 発展的な使い方: 複数の操作を部分的にロールバックすることで、柔軟なトランザクション管理が可能。

データベース操作を安全かつ効率的に行うために、自動コミットとロールバックの設定を適切に使用しましょう。

良かったらフォローお願いします

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です