019 例外と例外処理(トランザクションとロールバック) 032 解答例

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 例外と例外処理」問題集リスト