019 例外と例外処理(カスタム例外処理戦略) 027 解答例


以下は、Javaでの銀行取引をシミュレートするプログラムの簡単な解答例です。このプログラムでは、BankAccount クラスが銀行アカウントを表し、InsufficientFundsException が残高不足時にスローされるカスタム例外クラスです。トランザクションのロールバック処理も含まれています。

class InsufficientFundsException extends Exception {
    public InsufficientFundsException(String message) {
        super(message);
    }
}

class BankAccount {
    private String accountNumber;
    private double balance;

    public BankAccount(String accountNumber, double initialBalance) {
        this.accountNumber = accountNumber;
        this.balance = initialBalance;
    }

    public void deposit(double amount) {
        balance += amount;
        System.out.println("Deposited: " + amount);
        System.out.println("New Balance: " + balance);
    }

    public void withdraw(double amount) throws InsufficientFundsException {
        if (amount > balance) {
            throw new InsufficientFundsException("Insufficient funds. Withdrawal not allowed.");
        }

        balance -= amount;
        System.out.println("Withdrawn: " + amount);
        System.out.println("New Balance: " + balance);
    }

    // シミュレートのため、トランザクションのロールバックを実装
    public void rollback(double amount) {
        balance += amount;
        System.out.println("Transaction rolled back. New Balance: " + balance);
    }
}

public class BankTransactionSimulation {
    public static void main(String[] args) {
        BankAccount account = new BankAccount("12345", 1000.0);

        try {
            // 正常な取引
            account.deposit(500.0);

            // 残高不足で例外が発生する取引
            try {
                account.withdraw(2000.0);
            } catch (InsufficientFundsException e) {
                System.out.println(e.getMessage());
                account.rollback(500.0); // 残高不足のためロールバック
            }

            // 再度正常な取引
            account.withdraw(200.0);
        } catch (InsufficientFundsException e) {
            System.out.println(e.getMessage());
        }
    }
}

このプログラムでは、withdraw メソッド内で残高不足の場合に InsufficientFundsException をスローしています。その後、トランザクションがロールバックされています。このように、取引中にエラーが発生した場合には、トランザクションを元の状態に戻すことが重要です。

トランザクション処理の例外管理

トランザクション処理では、データベースや銀行取引などの一連の操作が原子的に行われることが期待されます。これはつまり、トランザクション内の一部の操作が失敗した場合、全体がロールバックされ、変更が適用されないということを指します。トランザクション処理において、例外管理は非常に重要です。以下に、トランザクション処理の例外管理のポイントと解説を示します。

  1. 例外の種類による分類:
    • 一般例外 (General Exception): プログラム全体を包括する広範な例外を指します。これらの例外は、特定のエラーが発生したことを示すものではありません。通常、開発者が意図的に特定の例外をキャッチする場合を除いて、避けるべきです。
    • 特定の例外 (Specific Exception): 特定のエラー状況に関連する例外。たとえば、データベース接続の喪失、SQL クエリの構文エラー、残高不足などが該当します。
  2. トランザクションのアトミシティ:
    • トランザクションはアトミック性を持ちます。これは、トランザクション内のすべての操作が成功するか、どれか一つでも失敗すると全てがロールバックされるという原則です。トランザクション内で例外が発生した場合、それを適切に処理してロールバックを行う必要があります。
  3. トランザクションのロールバック:
    • トランザクション内で問題が発生した場合、すべての変更を取り消し、トランザクションを元の状態に戻す必要があります。このプロセスをロールバックと呼びます。ロールバックは、データの整合性を保つために非常に重要です。
  4. データベーストランザクションの例外処理:
    • データベーストランザクションでは、SQL 実行時に例外が発生する可能性があります。SQL エラー、データベースの接続エラー、一意制約違反などが考えられます。これらの例外を適切に処理し、トランザクションをロールバックすることが必要です。
  5. トランザクション管理のベストプラクティス:
    • トランザクション内で発生する可能性のある例外をキャッチし、ロールバック処理を行う際には、エラーログに詳細な情報を記録すると良いでしょう。これにより、問題の特定と解決が容易になります。
try {
    // トランザクション開始
    // データベース更新などの処理

    // トランザクション成功
    commitTransaction();
} catch (SQLException e) {
    // データベーストランザクション内での例外処理
    rollbackTransaction();
    logError("Database Transaction Error", e);
} catch (InsufficientFundsException e) {
    // 自作例外など、特定のエラーに関連する例外処理
    rollbackTransaction();
    logError("Insufficient Funds Error", e);
} catch (Exception e) {
    // 一般的な例外処理
    rollbackTransaction();
    logError("General Error", e);
} finally {
    // トランザクション終了処理
    closeConnection

トランザクション処理の例外管理は、システムの信頼性とデータの整合性を確保するために不可欠です。適切な例外処理とロールバックが実装された場合、トランザクション内で発生する問題に柔軟に対応でき、エラーが発生してもデータベースやシステム全体が安全な状態に戻ることができます。

例外処理のポイントは、トランザクション内での操作がアトミックであること、つまり成功か失敗かのどちらか一方しか存在しないことを確認することです。これにより、トランザクションが不完全な状態になることを防ぎ、データの整合性を確保します。

適切な例外処理戦略を構築することで、システムは耐障害性を向上させ、ユーザーエクスペリエンスを向上させることができます。そして、発生したエラーに対して迅速に対応し、ログを通じて問題の追跡が容易になります。

トランザクション処理における例外管理は、データベースや取引などの重要な操作において特に重要であり、これによってシステム全体の信頼性が向上します。

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