java-beginner.com ブログ

プログラミングを学習するブログ(Javaをメインに)

ロールバックを使う

投稿日:

最終更新日:2016年09月29日

アイキャッチ

こんにちは。「Javaを復習する初心者」です。

今回はデータベースのロールバックを使ってみました。

今回はトランザクションの制御として、ロールバックを使ってみました。トランザクションとは送信する複数のSQLを一つのグループとして扱う考え方ですが、今回はひとつのUPDATE文の発行をひとつのトランザクションとします。トランザクションの処理結果を確定させることをコミットといい、実行前の状態に戻すことをロールバックといいます。今回はロールバックを確認しました。

データベース側

使うデータベースはH2DataBaseです。データの用意に使ったCREATE文とINSERT文は以下です。前回と同じです。

データの用意

DROP TABLE IF EXISTS SAMPLE_USER;

CREATE TABLE SAMPLE_USER (
  ID CHAR(10) not null primary key,
  NAME VARCHAR(255) not null,
  AGE INT not null,
  YEAR INT not null
);

INSERT INTO SAMPLE_USER (ID, NAME, AGE, YEAR) VALUES('A000000001', 'サンプル名前1', 20, 1);
INSERT INTO SAMPLE_USER (ID, NAME, AGE, YEAR) VALUES('A000000002', 'サンプル名前2', 21, 2);
INSERT INTO SAMPLE_USER (ID, NAME, AGE, YEAR) VALUES('A000000003', 'サンプル名前3', 20, 1);
INSERT INTO SAMPLE_USER (ID, NAME, AGE, YEAR) VALUES('A000000004', 'サンプル名前4', 21, 2);

Java側でロールバック

さて、ロールバックの実験ですが、ロールバック前後の状態を確認するために、以下のメソッドを作りました。

一覧表示のメソッド

    private static void select(Connection connection) {
        try (PreparedStatement ps = connection.prepareStatement("SELECT * FROM SAMPLE_USER ORDER BY ID")) {
            try (ResultSet rs = ps.executeQuery()) {
                while (rs.next()) {
                    System.out.println(rs.getString("id") + ","
                            + rs.getString("name") + ","
                            + rs.getString("age") + ","
                            + rs.getString("year"));
                }
                System.out.println();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

仮引数がConnectionクラスです。こうすることで接続中のデータベースに対して、SQLを発行するというメソッドを作ることができます。上記ではSAMPLE_USERテーブルのレコードをID順に表示するということをしています。順序を決める記述は、ORDER BY句です。

今回はmainメソッドの内容は以下です。

mainメソッドの内容

        try (Connection connection = DriverManager.getConnection("jdbc:h2:~/test", "sa", "")) {

            connection.setAutoCommit(false);

            System.out.println("UPDATE前");
            select(connection);

            try (PreparedStatement ps = connection.prepareStatement("UPDATE SAMPLE_USER SET YEAR = ? WHERE ID = ?")) {
                ps.setString(1, "99");
                ps.setString(2, "A000000001");
                ps.executeUpdate();
            } catch (Exception e) {
                 e.printStackTrace();
            }

            System.out.println("UPDATE後");
            select(connection);

            connection.rollback();

            System.out.println("ロールバック後");
            select(connection);

        } catch (Exception e) {
            e.printStackTrace();
        }

何も設定せずにUPDATE文を発行するとその時点でコミットされます。これはデフォルトの設定では、新しい接続は自動コミット・モードだからです。 これを解除するため、「connection.setAutoCommit(false);」を記述します。これでロールバックをすることが可能になります。

上記プログラムではひとつのUPDATE文を発行しています。IDがA000000001であるレコードのカラムYEARの値を更新しています。その前後で「select(connection);」を記述しています。SELECT文を発行して、コンソールにテーブルのレコードすべてを表示しています。

ロールバックを実行している個所は「connection.rollback();」です。この記述によって、ロールバックが実行されます。ロールバック後にテーブルのレコードすべてを表示しています。ロールバックでデータが元に戻ったのか確認するためです。

以下、実効結果です。

結果

UPDATE前
A000000001,サンプル名前1,20,1
A000000002,サンプル名前2,21,2
A000000003,サンプル名前3,20,1
A000000004,サンプル名前4,21,2

UPDATE後
A000000001,サンプル名前1,20,99
A000000002,サンプル名前2,21,2
A000000003,サンプル名前3,20,1
A000000004,サンプル名前4,21,2

ロールバック後
A000000001,サンプル名前1,20,1
A000000002,サンプル名前2,21,2
A000000003,サンプル名前3,20,1
A000000004,サンプル名前4,21,2

ロールバック後にA000000001のyearが1に戻っています。