/** * ドメイン非依存URL出力フィルタ * javadrill.tech移行時はwp_options.home/siteurlのみ変更すればよい * * データベースには絶対URL(https://minner.asia)を保持し、 * 表示時に現在のドメイン(home_url())に動的変換する */ function javadrill_make_urls_dynamic($content) { if (empty($content)) { return $content; } // データベース内の絶対URLを現在のhome_url()に置換 $old_url = 'https://minner.asia'; $new_url = untrailingslashit(home_url()); // http版も対応(念のため) $content = str_replace($old_url, $new_url, $content); $content = str_replace('http://minner.asia', $new_url, $content); return $content; } // 投稿本文、ウィジェット、タームの説明、抜粋に適用 add_filter('the_content', 'javadrill_make_urls_dynamic', 20); add_filter('widget_text', 'javadrill_make_urls_dynamic', 20); add_filter('term_description', 'javadrill_make_urls_dynamic', 20); add_filter('get_the_excerpt', 'javadrill_make_urls_dynamic', 20); 019 例外と例外処理 | Javaドリル https://minner.asia 楽々学べるJavaの問題集 Fri, 05 Sep 2025 02:00:18 +0000 ja hourly 1 https://wordpress.org/?v=6.8.3 https://minner.asia/wp-content/uploads/2023/10/cropped-logo-32x32.png 019 例外と例外処理 | Javaドリル https://minner.asia 32 32 019 例外と例外処理(トランザクションとロールバック) 035 解答例 https://minner.asia/archives/4485 https://minner.asia/archives/4485#respond Sun, 07 Jan 2024 22:34:50 +0000 http://localhost/?p=4485 ファイルの読み書きを伴うプログラムで、ファイルの書き込み中にエラーが発生した場合にトランザクションをロールバックし、エラーメッセージを表示するための簡単なJavaの例を以下に示します。この例では、FileWriter を使用してファイルにテキストを書き込みます。

import java.io.FileWriter;
import java.io.IOException;

public class FileReadWriteExample {

    public static void main(String[] args) {
        String filePath = "example.txt";

        try {
            // ファイルの書き込みトランザクション開始
            writeToFile(filePath, "Hello, World!");

            // ファイルへの書き込みが成功した場合の処理
            System.out.println("ファイルへの書き込みが成功しました。");

        } catch (IOException e) {
            // ファイルへの書き込み中にエラーが発生した場合の処理
            System.out.println("ファイルへの書き込み中にエラーが発生しました。");
            e.printStackTrace();

            // トランザクションのロールバック
            // ここで別の例外処理やロールバックのためのコードを追加することができます。
        }
    }

    private static void writeToFile(String filePath, String content) throws IOException {
        // ファイルを書き込む際に発生する例外をキャッチして、トランザクションをロールバックする
        try (FileWriter writer = new FileWriter(filePath)) {
            writer.write(content);
        }
    }
}

この例では、FileWriter でファイルに書き込みを行います。writeToFile メソッド内でファイルへの書き込みが行われ、もしIOException が発生した場合には、それをキャッチしてエラーメッセージを表示し、トランザクションをロールバックします。これはファイルの書き込みが失敗した場合に実行されるエラーハンドリングの一例です。

ファイル処理のトランザクションとロールバック

ファイル処理におけるトランザクションとロールバックは、データベースのトランザクションと同じような考え方を適用するもので、特定の一連の操作がまとまりとして扱われ、それらの操作が全て成功した場合に変更を確定させ、途中でエラーが発生した場合には変更を元に戻すという仕組みです。

以下に、Javaを使用した簡単なファイル処理のトランザクションとロールバックを模擬する例を示します。この例では、ファイルへの書き込みトランザクションを開始し、書き込み中にエラーが発生した場合にロールバックする仮想的な概念を取り入れています。

import java.io.FileWriter;
import java.io.IOException;

public class FileTransactionExample {

    public static void main(String[] args) {
        String filePath = "example.txt";

        // ファイルへのトランザクション開始
        try (FileTransaction transaction = new FileTransaction(filePath)) {
            // ファイルへの書き込み
            transaction.writeToFile("Hello, World!");

            // トランザクションのコミット(正常終了)
            transaction.commit();

        } catch (IOException e) {
            // トランザクション中にエラーが発生した場合の処理
            System.out.println("トランザクション中にエラーが発生しました。");
            e.printStackTrace();
        }
    }

    private static class FileTransaction implements AutoCloseable {
        private final String filePath;
        private boolean committed;

        public FileTransaction(String filePath) {
            this.filePath = filePath;
            this.committed = false;
        }

        public void writeToFile(String content) throws IOException {
            // ファイルへの書き込み中にエラーが発生する可能性を考慮した処理
            // (例えば、ファイルが存在しない場合や書き込み権限がない場合)
            try (FileWriter writer = new FileWriter(filePath)) {
                writer.write(content);
            }
        }

        public void commit() {
            committed = true;
        }

        @Override
        public void close() throws IOException {
            // トランザクションのロールバック処理
            if (!committed) {
                System.out.println("トランザクションがロールバックされました。");
                // ファイルの変更を元に戻すためのロールバック処理をここに追加する
            }
        }
    }
}

FileTransaction クラスの役割:

  • FileTransaction クラスは、トランザクションの単位を表します。これは AutoCloseable インターフェースを実装しており、try-with-resources 文で使用できます。
  • ファイルパスとトランザクションのコミット状態を管理します。
private static class FileTransaction implements AutoCloseable {
    private final String filePath;
    private boolean committed;

    // コンストラクタ
    public FileTransaction(String filePath) {
        this.filePath = filePath;
        this.committed = false;
    }
}

トランザクション内のファイル書き込み:

  • writeToFile メソッドは、トランザクション内でファイルに書き込む操作を担当します。
  • トランザクション中にエラーが発生しない限り、このメソッドでのファイル書き込みはコミットされることになります。
public void writeToFile(String content) throws IOException {
    try (FileWriter writer = new FileWriter(filePath)) {
        writer.write(content);
    }
}

トランザクションのコミット:

  • commit メソッドは、トランザクションが正常に終了したことを示します。
public void commit() {
    committed = true;
}

トランザクションのクローズ (AutoCloseable インターフェース):

  • close メソッドは AutoCloseable インターフェースの一部であり、try-with-resources ブロックが終了する際に呼び出されます。
  • このメソッドでは、トランザクションが正常に終了していない場合、ロールバック処理が行われます。
@Override
public void close() throws IOException {
    // トランザクションのロールバック処理
    if (!committed) {
        // ファイルの変更を元に戻すためのロールバック処理をここに追加する
    }
}

トランザクションの利用:

main メソッドでは、try-with-resources 文を使用してトランザクションを開始し、ファイルへの書き込みを行います。このとき、トランザクション中にエラーが発生すると、FileTransaction クラスの close メソッドが呼ばれ、ロールバック処理が行われます。

try (FileTransaction transaction = new FileTransaction(filePath)) {
    // ファイルへの書き込み
    transaction.writeToFile("Hello, World!");

    // トランザクションのコミット(正常終了)
    transaction.commit();
} catch (IOException e) {
    // トランザクション中にエラーが発生した場合の処理
    System.out.println("トランザクション中にエラーが発生しました。");
    e.printStackTrace();
}

このように、ファイル処理におけるトランザクションとロールバックは、エラーが発生した場合に変更を取り消すメカニズムを提供し、データの整合性を維持します。ただし、データベースのトランザクションとは異なり、ファイル処理においては永続性などが直接的に提供されないことに留意する必要があります。

ァイル処理におけるトランザクションとロールバックは、データ整合性とエラー処理の面で重要な概念です。これにより、ファイルへの変更が途中でエラーを引き起こした場合でも、データが矛盾せず、安全に復元できるメカニズムが提供されます。

重要なポイントとして、ファイル処理のトランザクションはデータベースのトランザクションとは異なり、データの永続性が直接的にサポートされないことが挙げられます。そのため、トランザクションの範囲内での変更は、アプリケーション内でのみ影響を及ぼします。

トランザクションとロールバックを利用することで、ファイル処理においても信頼性の高いデータ管理が可能となります。エラーへの柔軟な対応やデータ整合性の確保は、堅牢で安全なファイル処理アプリケーションを構築する上で不可欠なスキルとなります。

「019 例外と例外処理」問題集リスト

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/4485/feed 0
019 例外と例外処理(トランザクションとロールバック) 035 問題 https://minner.asia/archives/4483 https://minner.asia/archives/4483#respond Sun, 07 Jan 2024 22:10:36 +0000 http://localhost/?p=4483

問題

ファイルの読み書きを伴うプログラムを作成します。ファイルの書き込み中にエラーが発生した場合、トランザクションをロールバックし、エラーメッセージを表示してください。

ヒント

  1. try-with-resourcesを使用: ファイルを開く部分で try-with-resources 文を使用して、ファイルリソースを確実にクローズします。
  2. トランザクション管理: ファイルの書き込みがトランザクションと考え、正常に完了した場合はコミットし、エラーが発生した場合はロールバックします。
  3. 例外処理: ファイルの書き込み中に発生する可能性のある例外(例: IOException)を捕捉して、エラーメッセージを表示し、トランザクションをロールバックします。

これらの基本的な手順に従って、ファイルの書き込み中にエラーが発生した場合にトランザクションをロールバックし、エラーメッセージを表示するプログラムを実装できます。

→解答例

「019 例外と例外処理」問題集リスト

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/4483/feed 0
019 例外と例外処理(トランザクションとロールバック) 034 解答例 https://minner.asia/archives/4479 https://minner.asia/archives/4479#respond Sun, 07 Jan 2024 22:06:19 +0000 http://localhost/?p=4479 以下は、データベース内の複数のテーブルに変更を加え、一部のテーブルでの変更が成功し、他のテーブルでの変更が失敗した場合にトランザクションをロールバックし、エラーメッセージを表示するJavaの例です。なお、具体的なデータベースやテーブルの構造に合わせて変更する必要があります。

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

public class MultiTableTransactionExample {

    // データベース接続情報
    private static final String JDBC_URL = "jdbc:mysql://localhost:3306/your_database";
    private static final String USER = "your_username";
    private static final String PASSWORD = "your_password";

    public static void main(String[] args) {
        try (Connection connection = DriverManager.getConnection(JDBC_URL, USER, PASSWORD)) {
            // トランザクション開始
            connection.setAutoCommit(false);

            try {
                // テーブル1の変更
                updateTable1(connection);

                // テーブル2の変更
                updateTable2(connection);

                // すべての変更が成功した場合、トランザクションをコミット
                connection.commit();
                System.out.println("トランザクションが正常に完了しました。");
            } catch (SQLException e) {
                // 何かしらのエラーが発生した場合、トランザクションをロールバック
                connection.rollback();
                System.err.println("トランザクションがロールバックされました。エラー: " + e.getMessage());
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private static void updateTable1(Connection connection) throws SQLException {
        // テーブル1の変更処理
        String sql = "UPDATE table1 SET column1 = ? WHERE id = ?";
        try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
            // パラメータをセット
            preparedStatement.setString(1, "new_value");
            preparedStatement.setInt(2, 1);
            // 実行
            preparedStatement.executeUpdate();
        } catch (SQLException e) {
            // テーブル1の変更でエラーが発生した場合
            throw new SQLException("テーブル1の変更中にエラーが発生しました。", e);
        }
    }

    private static void updateTable2(Connection connection) throws SQLException {
        // テーブル2の変更処理
        String sql = "UPDATE table2 SET column1 = ? WHERE id = ?";
        try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
            // パラメータをセット
            preparedStatement.setString(1, "new_value");
            preparedStatement.setInt(2, 1);
            // 実行(ここでは敢えてエラーを発生させる)
            preparedStatement.executeUpdate();
        } catch (SQLException e) {
            // テーブル2の変更でエラーが発生した場合
            throw new SQLException("テーブル2の変更中にエラーが発生しました。", e);
        }
    }
}

この例では、updateTable1メソッドとupdateTable2メソッドがそれぞれ異なるテーブルの変更を担当しています。トランザクション内でのエラー発生時には、トランザクション全体をロールバックしています。

「019 例外と例外処理」問題集リスト

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/4479/feed 0
019 例外と例外処理(トランザクションとロールバック) 034 問題 https://minner.asia/archives/4476 https://minner.asia/archives/4476#respond Sun, 07 Jan 2024 22:02:03 +0000 http://localhost/?p=4476

問題

データベース内の複数のテーブルに変更を加えるプログラムを作成します。一部のテーブルでの変更が成功し、他のテーブルでの変更が失敗した場合、トランザクションをロールバックし、エラーメッセージを表示してください。

ヒント

  1. トランザクションの開始と終了:
    • トランザクションは複数のデータベース操作をまとめて処理するために使用されます。トランザクションは必要に応じて開始し、正常に完了した場合にはコミットし、エラーが発生した場合にはロールバックします。
  2. 各テーブルでの変更:
    • 各テーブルに対する変更は、それぞれのメソッドで行います。各メソッド内でのデータベースの更新処理を記述します。
  3. エラー処理:
    • 各メソッド内でエラーが発生した場合、トランザクション全体をロールバックする必要があります。これにより、変更が一部だけ実行されていた場合でもデータベースが一貫性を保ちます。
  4. トランザクションのコミットとロールバック:
    • すべての変更が成功した場合、トランザクションをコミットします。逆に、どれか一つでもエラーが発生した場合、トランザクションをロールバックします。

これらのポイントを考慮して、複数のテーブルに変更を加えるプログラムを作成してください。

→解答例

「019 例外と例外処理」問題集リスト

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/4476/feed 0
019 例外と例外処理(トランザクションとロールバック) 033 解答例 https://minner.asia/archives/4471 https://minner.asia/archives/4471#respond Sun, 07 Jan 2024 21:56:51 +0000 http://localhost/?p=4471
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class ReservationProgram {
    // データベース接続情報
    private static final String JDBC_URL = "jdbc:mysql://localhost:3306/reservation_db";
    private static final String USER = "username";
    private static final String PASSWORD = "password";

    // 予約を行うメソッド
    public void makeReservation(String facility, String dateTime) {
        try (Connection connection = DriverManager.getConnection(JDBC_URL, USER, PASSWORD)) {
            // トランザクションの開始
            connection.setAutoCommit(false);

            // 予約の重複チェック
            if (!isReservationAvailable(connection, facility, dateTime)) {
                // 予約が重複している場合、トランザクションをロールバック
                connection.rollback();
                System.out.println("予約が重複しています。");
                return;
            }

            // 予約をデータベースに登録
            insertReservation(connection, facility, dateTime);

            // トランザクションのコミット
            connection.commit();

            System.out.println("予約が完了しました。");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    // 予約の重複チェックを行うメソッド
    private boolean isReservationAvailable(Connection connection, String facility, String dateTime)
            throws SQLException {
        String sql = "SELECT COUNT(*) FROM reservations WHERE facility = ? AND date_time = ?";
        try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
            preparedStatement.setString(1, facility);
            preparedStatement.setString(2, dateTime);

            // 予約がある場合は false を返す
            return preparedStatement.executeQuery().getInt(1) == 0;
        }
    }

    // 予約をデータベースに登録するメソッド
    private void insertReservation(Connection connection, String facility, String dateTime)
            throws SQLException {
        String sql = "INSERT INTO reservations (facility, date_time) VALUES (?, ?)";
        try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
            preparedStatement.setString(1, facility);
            preparedStatement.setString(2, dateTime);

            preparedStatement.executeUpdate();
        }
    }

    public static void main(String[] args) {
        ReservationProgram reservationProgram = new ReservationProgram();
        reservationProgram.makeReservation("Conference Room A", "2023-01-01 14:00");
    }
}
  1. makeReservation メソッド内でトランザクションを開始し、予約の重複チェックを行います。
  2. isReservationAvailable メソッドで指定された施設と日時に既に予約があるかどうかを確認します。
  3. 予約が重複している場合、トランザクションをロールバックし、エラーメッセージを表示して処理を終了します。
  4. 予約が重複していない場合、insertReservation メソッドで新しい予約をデータベースに登録します。
  5. トランザクションのコミットを行い、予約が完了した旨のメッセージを表示します。

「019 例外と例外処理」問題集リスト

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/4471/feed 0
019 例外と例外処理(トランザクションとロールバック) 033 問題 https://minner.asia/archives/4468 https://minner.asia/archives/4468#respond Sun, 07 Jan 2024 21:52:27 +0000 http://localhost/?p=4468

問題

ユーザーがイベントや施設を予約するプログラムを作成してください。予約が重複している場合、トランザクションをロールバックし、エラーメッセージを表示してください。

ヒント

  1. トランザクションの開始: データベースのトランザクションを開始します。これにより、複数の SQL ステートメントがアトミックに処理されます。
  2. 予約の重複チェック: 予約が重複していないかデータベースで確認します。例えば、同じ施設やイベントに同じ日時での予約が存在しないかを確認します。
  3. 予約の登録: 予約が重複していなければ、新しい予約をデータベースに登録します。
  4. コミット: トランザクション内の操作がすべて成功した場合、トランザクションをコミットして変更を確定します。
  5. ロールバック: 予約が重複している場合、トランザクションをロールバックし、エラーメッセージを表示します。

上記の手順を参考に、トランザクションのコントロールと予約の重複チェックを行うプログラムを作成できます。データベースのスキーマや使用する言語によって具体的な実装が異なりますが、一般的な流れは上記の通りです。

→解答例

「019 例外と例外処理」問題集リスト

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/4468/feed 0
019 例外と例外処理(トランザクションとロールバック) 032 解答例 https://minner.asia/archives/4463 https://minner.asia/archives/4463#respond Sun, 07 Jan 2024 21:49:14 +0000 http://localhost/?p=4463
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class InventoryManagement {
    private static final String DB_URL = "jdbc:mysql://localhost:3306/inventory";
    private static final String USER = "username";
    private static final String PASSWORD = "password";

    public static void main(String[] args) {
        // 商品の購入情報(例として商品IDと購入数量を仮定)
        int productId = 1;
        int purchaseQuantity = 10;

        // データベースへの接続
        try (Connection connection = DriverManager.getConnection(DB_URL, USER, PASSWORD)) {
            // トランザクションの開始
            connection.setAutoCommit(false);

            // 在庫数量の取得
            int currentStock = getCurrentStock(connection, productId);

            // 在庫が足りているか確認
            if (currentStock >= purchaseQuantity) {
                // 購入処理の実行
                updateStock(connection, productId, currentStock - purchaseQuantity);

                // トランザクションのコミット
                connection.commit();
                System.out.println("購入が完了しました。");
            } else {
                // 在庫が不足している場合、ロールバックとエラーメッセージの表示
                connection.rollback();
                System.out.println("在庫が不足しています。購入できませんでした。");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private static int getCurrentStock(Connection connection, int productId) throws SQLException {
        // 商品IDを元に現在の在庫数量を取得するSQL文
        String sql = "SELECT stock FROM products WHERE product_id = ?";
        try (PreparedStatement statement = connection.prepareStatement(sql)) {
            statement.setInt(1, productId);
            // SQLの実行
            var resultSet = statement.executeQuery();
            if (resultSet.next()) {
                return resultSet.getInt("stock");
            } else {
                throw new SQLException("商品が見つかりませんでした。");
            }
        }
    }

    private static void updateStock(Connection connection, int productId, int newStock) throws SQLException {
        // 商品IDを元に在庫数量を更新するSQL文
        String sql = "UPDATE products SET stock = ? WHERE product_id = ?";
        try (PreparedStatement statement = connection.prepareStatement(sql)) {
            statement.setInt(1, newStock);
            statement.setInt(2, productId);
            // SQLの実行
            statement.executeUpdate();
        }
    }
}
  1. main メソッドでは、トランザクションの開始から終了までの流れを記述しています。try-with-resources 文を使用して、自動的にクローズされる Connection オブジェクトを取得します。
  2. getCurrentStock メソッドは、商品IDを元に現在の在庫数量をデータベースから取得します。
  3. updateStock メソッドは、商品IDを元に在庫数量を更新します。
  4. 購入処理が行われる前に在庫が足りているか確認し、足りている場合は購入処理を実行してコミットします。在庫が不足している場合はロールバックし、エラーメッセージを表示します。

このプログラムでは、トランザクションの制御により、購入処理が途中で失敗した場合にデータベースの状態が一貫性を保つようにしています。

「019 例外と例外処理」問題集リスト

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/4463/feed 0
019 例外と例外処理(トランザクションとロールバック) 032 問題 https://minner.asia/archives/4460 https://minner.asia/archives/4460#respond Sun, 07 Jan 2024 21:44:35 +0000 http://localhost/?p=4460

問題

商品の在庫を管理するプログラムを作成します。商品の購入が行われた場合、購入数量が在庫数量を超える場合、トランザクションをロールバックし、エラーメッセージを表示してください。

ヒント

  1. トランザクションの開始: 購入処理をトランザクションで囲みます。これにより、一連の操作がまとまって実行され、成功または失敗が保証されます。
  2. 在庫の確認: 購入前に在庫数量を確認します。在庫が購入数量を超えているかどうかを確認します。
  3. 条件分岐: 在庫が足りている場合、購入処理を実行します。在庫が不足している場合は、トランザクションをロールバックします。
  4. エラーメッセージの表示: ロールバックが発生した場合、ユーザーにエラーメッセージを表示します。このメッセージには在庫が不足している旨や他に必要な情報が含まれると良いでしょう。

トランザクションとロールバックの利用は、データの整合性を確保する重要な手段です。これにより、システムが一貫性を持ち、異常な状態が発生した場合にデータが破損することを防ぐことができます。

→解答例

「019 例外と例外処理」問題集リスト

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/4460/feed 0
019 例外と例外処理(トランザクションとロールバック) 031 解答例 https://minner.asia/archives/4454 https://minner.asia/archives/4454#respond Sun, 07 Jan 2024 21:34:41 +0000 http://localhost/?p=4454 以下は、Javaでの簡単な銀行取引プログラムの解答例と解説です。この例では、送金元のアカウントに十分な残高がない場合にトランザクションをロールバックし、エラーメッセージを表示します。データベースのトランザクションは try-with-resources 文を使用して確実にクローズされるようにします。

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

// カスタム例外クラス
class InsufficientFundsException extends Exception {
    public InsufficientFundsException(String message) {
        super(message);
    }
}

public class BankTransactionExample {
    private static final String DB_URL = "jdbc:mysql://localhost:3306/bank";
    private static final String DB_USER = "your_username";
    private static final String DB_PASSWORD = "your_password";

    // 銀行取引メソッド
    public static void transferFunds(int fromAccount, int toAccount, double amount) throws SQLException, InsufficientFundsException {
        // データベースへの接続
        try (Connection connection = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            // トランザクションの開始
            connection.setAutoCommit(false);

            // 送金元の残高取得
            double balance = getAccountBalance(connection, fromAccount);

            // 残高が十分か確認
            if (balance < amount) {
                // 残高不足の場合、トランザクションをロールバックし例外をスロー
                connection.rollback();
                throw new InsufficientFundsException("送金元アカウントの残高が不足しています。");
            }

            // 送金元アカウントから引き落とし
            updateAccountBalance(connection, fromAccount, balance - amount);

            // 送金先アカウントに入金
            updateAccountBalance(connection, toAccount, getAccountBalance(connection, toAccount) + amount);

            // トランザクションをコミット
            connection.commit();
        }
    }

    // 指定されたアカウントの残高を取得するメソッド
    private static double getAccountBalance(Connection connection, int accountNumber) throws SQLException {
        String query = "SELECT balance FROM accounts WHERE account_number = ?";
        try (PreparedStatement preparedStatement = connection.prepareStatement(query)) {
            preparedStatement.setInt(1, accountNumber);
            var resultSet = preparedStatement.executeQuery();
            if (resultSet.next()) {
                return resultSet.getDouble("balance");
            }
            throw new SQLException("アカウントが見つかりません。");
        }
    }

    // 指定されたアカウントの残高を更新するメソッド
    private static void updateAccountBalance(Connection connection, int accountNumber, double newBalance) throws SQLException {
        String query = "UPDATE accounts SET balance = ? WHERE account_number = ?";
        try (PreparedStatement preparedStatement = connection.prepareStatement(query)) {
            preparedStatement.setDouble(1, newBalance);
            preparedStatement.setInt(2, accountNumber);
            int affectedRows = preparedStatement.executeUpdate();
            if (affectedRows == 0) {
                throw new SQLException("アカウントが見つかりません。");
            }
        }
    }

    public static void main(String[] args) {
        try {
            // ユーザーがアカウント間で資金を移動する例
            transferFunds(123456, 789012, 1000.0);
            System.out.println("取引が成功しました。");
        } catch (SQLException | InsufficientFundsException e) {
            System.err.println("取引エラー: " + e.getMessage());
        }
    }
}

この例では、InsufficientFundsException が送金元アカウントの残高不足時にスローされます。トランザクションの管理が重要であり、残高が十分でない場合はトランザクションをロールバックし、変更を元に戻します。

トランザクションとロールバック

1. トランザクションの概要

トランザクションは、データベースの一連の操作を意味します。これらの操作は、成功するか失敗するかのいずれかで、トランザクション全体が原子性を持ちます。原子性とは、トランザクションが全体として成功するか、全体として失敗するかのいずれかであることを指します。原子性が保たれない場合、途中でエラーが発生してもトランザクションの一部がデータベースに変更を加えた可能性があります。

2. トランザクションの管理

トランザクションの管理はデータベース接続を使用して行います。トランザクションは通常、以下の手順で実行されます。

  • トランザクションの開始: トランザクション内の操作が始まることをデータベースに通知します。これにより、トランザクションが始まり、それに関連する操作が原子的になります。
  • トランザクションのコミット: トランザクションが成功した場合、変更をデータベースに確定させます。これにより、トランザクション内で行われた変更がデータベースに永続的に反映されます。
  • トランザクションのロールバック: トランザクションが失敗した場合、変更を取り消し、トランザクション内で行われたすべての変更を元に戻します。

3. トランザクションとロールバックの重要性

トランザクションとロールバックはデータベースの一貫性を保つために非常に重要です。トランザクション内でエラーが発生した場合、ロールバックを行うことで、変更を取り消し、データベースを前の状態に戻すことができます。これにより、データの整合性が保たれ、データベースが信頼性を維持します。

4. サンプルプログラムの解説

サンプルプログラムでは、transferFunds メソッド内でトランザクションが開始され、成功するか失敗するかが判断されています。残高不足の場合、InsufficientFundsException がスローされ、トランザクションがロールバックされます。ロールバックは connection.rollback() で行います。

try (Connection connection = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
    // トランザクションの開始
    connection.setAutoCommit(false);

    // 送金元の残高取得
    double balance = getAccountBalance(connection, fromAccount);

    // 残高が十分か確認
    if (balance < amount) {
        // 残高不足の場合、トランザクションをロールバックし例外をスロー
        connection.rollback();
        throw new InsufficientFundsException("送金元アカウントの残高が不足しています。");
    }

    // ...(以下略)
    
    // トランザクションをコミット
    connection.commit();
}

このように、トランザクションとロールバックを使用することで、データベースの一貫性を確保し、エラーが発生した場合に適切に対処できます。

トランザクションとロールバックはデータベース処理において欠かせない概念であり、データの整合性や信頼性を確保するために重要な役割を果たします。トランザクションは一連のデータベース操作を原子的にまとめ、全体が成功するか失敗するかを保証します。ロールバックはトランザクション内でエラーが発生した場合に変更を取り消し、データベースを前の状態に戻します。

データベース取引においては、エラーが発生する可能性があるため、トランザクションとロールバックの理解と適切な利用が不可欠です。これにより、データベースが一貫性を保ち、システムが信頼性を確保できます。

適切なトランザクション管理はデータベース処理の安定性と信頼性に直結し、開発者がシステム全体の一貫性を維持できるようサポートします。

「019 例外と例外処理」問題集リスト

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/4454/feed 0
019 例外と例外処理(トランザクションとロールバック) 031 問題 https://minner.asia/archives/4451 https://minner.asia/archives/4451#respond Sun, 07 Jan 2024 21:24:07 +0000 http://localhost/?p=4451

問題

ユーザーがアカウント間で資金を移動する銀行取引プログラムを作成してください。ただし、送金元のアカウントに十分な残高がない場合、トランザクションをロールバックし、適切なエラーメッセージを表示してください。

ヒント

  1. トランザクションの開始: 銀行取引が始まる際にトランザクションを開始します。この際、データベースなどのリソースへのアクセスが増えます。
  2. トランザクション内での処理: 銀行取引の途中で何らかのエラーが発生した場合、トランザクションをロールバックします。これにより、途中で発生した変更が元に戻ります。
  3. トランザクションのコミット: 銀行取引が正常に完了した場合、トランザクションをコミットして変更を確定します。
  4. エラーのハンドリング: 例えば、送金元のアカウントに十分な残高がない場合、トランザクションをロールバックし、エラーメッセージを表示します。
  5. コードの構造: メソッドなどでトランザクション処理を適切に構造化し、可読性と保守性を向上させます。

これらのヒントを元に、トランザクション処理の流れを考えてみてください。

→解答例

「019 例外と例外処理」問題集リスト

🎯 実習で理解を深めよう

この内容についてJavaDrillで実際に手を動かして学習できます

]]>
https://minner.asia/archives/4451/feed 0