コンテンツにスキップ

Java Database Connectivity

出典: フリー教科書『ウィキブックス(Wikibooks)』

はじめに

[編集]

Java Database Connectivity(JDBC)は、Javaアプリケーションがリレーショナルデータベースと対話するための標準APIです。JDBCを使用することで、開発者はデータベースへの接続、SQLクエリの実行、結果の取得などを行うことができます。本ハンドブックでは、JDBCの基本的な概念から応用的な使い方までを解説し、実際のコード例や表を交えながら理解を深めていきます。

第1章 JDBCの基本

[編集]

1.1 JDBCの概要

[編集]

JDBCは、Javaアプリケーションとデータベース間の橋渡し役を果たします。JDBC APIは、データベースベンダーが提供するJDBCドライバを介して、特定のデータベースと通信します。JDBCドライバは、Javaアプリケーションからのリクエストをデータベースが理解できる形式に変換し、その結果をJavaアプリケーションに返します。

1.2 JDBCアーキテクチャ

[編集]

JDBCアーキテクチャは、主に以下のコンポーネントで構成されています。

  1. JDBC API: Javaアプリケーションがデータベースと対話するためのインターフェースを提供します。
  2. JDBC Driver Manager: アプリケーションと適切なJDBCドライバを接続します。
  3. JDBC Driver: データベースベンダーが提供するドライバで、Javaアプリケーションとデータベース間の通信を実現します。
  4. データベース: 実際のデータを格納するリレーショナルデータベース。

1.3 JDBCドライバの種類

[編集]

JDBCドライバには、以下の4つのタイプがあります。

  1. タイプ1: JDBC-ODBCブリッジドライバ
  2. タイプ2: ネイティブAPIドライバ
  3. タイプ3: ネットワークプロトコルドライバ
  4. タイプ4: ネイティブプロトコルドライバ

現在では、タイプ4のドライバが最も一般的に使用されています。これは、純粋なJavaで実装されており、データベースと直接通信するため、パフォーマンスが高いからです。

第2章 JDBCの基本的な使い方

[編集]

2.1 データベースへの接続

[編集]

JDBCを使用してデータベースに接続するためには、まず適切なJDBCドライバをロードし、Connectionオブジェクトを取得する必要があります。以下は、MySQLデータベースに接続する例です。

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

public class JDBCExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/mydatabase";
        String username = "root";
        String password = "password";

        try {
            // JDBCドライバをロード
            Class.forName("com.mysql.cj.jdbc.Driver");

            // データベースに接続
            Connection connection = DriverManager.getConnection(url, username, password);
            System.out.println("データベースに接続しました。");

            // 接続を閉じる
            connection.close();
        } catch (ClassNotFoundException e) {
            System.out.println("JDBCドライバが見つかりませんでした。");
            e.printStackTrace();
        } catch (SQLException e) {
            System.out.println("データベース接続中にエラーが発生しました。");
            e.printStackTrace();
        }
    }
}

2.2 SQLクエリの実行

[編集]

データベースに接続したら、SQLクエリを実行することができます。以下は、Statementオブジェクトを使用してSQLクエリを実行する例です。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCQueryExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/mydatabase";
        String username = "root";
        String password = "password";

        try {
            // JDBCドライバをロード
            Class.forName("com.mysql.cj.jdbc.Driver");

            // データベースに接続
            Connection connection = DriverManager.getConnection(url, username, password);

            // Statementオブジェクトを作成
            Statement statement = connection.createStatement();

            // SQLクエリを実行
            String sql = "SELECT id, name, age FROM users";
            ResultSet resultSet = statement.executeQuery(sql);

            // 結果を処理
            while (resultSet.next()) {
                int id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                int age = resultSet.getInt("age");
                System.out.println("ID: " + id + ", Name: " + name + ", Age: " + age);
            }

            // リソースを解放
            resultSet.close();
            statement.close();
            connection.close();
        } catch (ClassNotFoundException e) {
            System.out.println("JDBCドライバが見つかりませんでした。");
            e.printStackTrace();
        } catch (SQLException e) {
            System.out.println("データベース操作中にエラーが発生しました。");
            e.printStackTrace();
        }
    }
}

2.3 プリペアドステートメントの使用

[編集]

プリペアドステートメントは、SQLインジェクションを防ぐために使用されます。以下は、プリペアドステートメントを使用してデータを挿入する例です。

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

public class JDBCPreparedStatementExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/mydatabase";
        String username = "root";
        String password = "password";

        try {
            // JDBCドライバをロード
            Class.forName("com.mysql.cj.jdbc.Driver");

            // データベースに接続
            Connection connection = DriverManager.getConnection(url, username, password);

            // プリペアドステートメントを作成
            String sql = "INSERT INTO users (name, age) VALUES (?, ?)";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);

            // パラメータを設定
            preparedStatement.setString(1, "John Doe");
            preparedStatement.setInt(2, 30);

            // SQLクエリを実行
            int rowsInserted = preparedStatement.executeUpdate();
            System.out.println(rowsInserted + "行が挿入されました。");

            // リソースを解放
            preparedStatement.close();
            connection.close();
        } catch (ClassNotFoundException e) {
            System.out.println("JDBCドライバが見つかりませんでした。");
            e.printStackTrace();
        } catch (SQLException e) {
            System.out.println("データベース操作中にエラーが発生しました。");
            e.printStackTrace();
        }
    }
}

第3章 トランザクション管理

[編集]

3.1 トランザクションの基本

[編集]

トランザクションは、複数のSQL操作を1つの単位として扱うための仕組みです。トランザクションを使用することで、すべての操作が成功した場合にのみ変更をコミットし、いずれかの操作が失敗した場合にはロールバックすることができます。

3.2 トランザクションの使用例

[編集]

以下は、トランザクションを使用して複数のSQL操作を実行する例です。

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

public class JDBCTransactionExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/mydatabase";
        String username = "root";
        String password = "password";

        Connection connection = null;

        try {
            // JDBCドライバをロード
            Class.forName("com.mysql.cj.jdbc.Driver");

            // データベースに接続
            connection = DriverManager.getConnection(url, username, password);

            // 自動コミットを無効にする
            connection.setAutoCommit(false);

            // プリペアドステートメントを作成
            String sql1 = "INSERT INTO users (name, age) VALUES (?, ?)";
            PreparedStatement preparedStatement1 = connection.prepareStatement(sql1);
            preparedStatement1.setString(1, "Alice");
            preparedStatement1.setInt(2, 25);
            preparedStatement1.executeUpdate();

            String sql2 = "UPDATE users SET age = ? WHERE name = ?";
            PreparedStatement preparedStatement2 = connection.prepareStatement(sql2);
            preparedStatement2.setInt(1, 26);
            preparedStatement2.setString(2, "Alice");
            preparedStatement2.executeUpdate();

            // トランザクションをコミット
            connection.commit();
            System.out.println("トランザクションがコミットされました。");

            // リソースを解放
            preparedStatement1.close();
            preparedStatement2.close();
        } catch (ClassNotFoundException e) {
            System.out.println("JDBCドライバが見つかりませんでした。");
            e.printStackTrace();
        } catch (SQLException e) {
            System.out.println("トランザクション中にエラーが発生しました。ロールバックします。");
            try {
                if (connection != null) {
                    connection.rollback();
                }
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

第4章 高度なJDBC機能

[編集]

4.1 バッチ処理

[編集]

バッチ処理を使用すると、複数のSQLクエリを一度に実行することができます。これにより、データベースとの通信回数を減らし、パフォーマンスを向上させることができます。

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

public class JDBCBatchExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/mydatabase";
        String username = "root";
        String password = "password";

        try {
            // JDBCドライバをロード
            Class.forName("com.mysql.cj.jdbc.Driver");

            // データベースに接続
            Connection connection = DriverManager.getConnection(url, username, password);

            // プリペアドステートメントを作成
            String sql = "INSERT INTO users (name, age) VALUES (?, ?)";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);

            // バッチにクエリを追加
            preparedStatement.setString(1, "Bob");
            preparedStatement.setInt(2, 28);
            preparedStatement.addBatch();

            preparedStatement.setString(1, "Charlie");
            preparedStatement.setInt(2, 22);
            preparedStatement.addBatch();

            // バッチを実行
            int[] rowsInserted = preparedStatement.executeBatch();
            System.out.println(rowsInserted.length + "行が挿入されました。");

            // リソースを解放
            preparedStatement.close();
            connection.close();
        } catch (ClassNotFoundException e) {
            System.out.println("JDBCドライバが見つかりませんでした。");
            e.printStackTrace();
        } catch (SQLException e) {
            System.out.println("バッチ処理中にエラーが発生しました。");
            e.printStackTrace();
        }
    }
}

4.2 ストアドプロシージャの呼び出し

[編集]

ストアドプロシージャは、データベースに保存された一連のSQLステートメントです。JDBCを使用してストアドプロシージャを呼び出すことができます。

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

public class JDBCCallableStatementExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/mydatabase";
        String username = "root";
        String password = "password";

        try {
            // JDBCドライバをロード
            Class.forName("com.mysql.cj.jdbc.Driver");

            // データベースに接続
            Connection connection = DriverManager.getConnection(url, username, password);

            // ストアドプロシージャを呼び出す
            String sql = "{call get_user_age(?, ?)}";
            CallableStatement callableStatement = connection.prepareCall(sql);

            // パラメータを設定
            callableStatement.setString(1, "Alice");
            callableStatement.registerOutParameter(2, java.sql.Types.INTEGER);

            // ストアドプロシージャを実行
            callableStatement.execute();

            // 結果を取得
            int age = callableStatement.getInt(2);
            System.out.println("Aliceの年齢は " + age + " 歳です。");

            // リソースを解放
            callableStatement.close();
            connection.close();
        } catch (ClassNotFoundException e) {
            System.out.println("JDBCドライバが見つかりませんでした。");
            e.printStackTrace();
        } catch (SQLException e) {
            System.out.println("ストアドプロシージャの呼び出し中にエラーが発生しました。");
            e.printStackTrace();
        }
    }
}

第5章 JDBCのベストプラクティス

[編集]

5.1 リソースの解放

[編集]

JDBCを使用する際には、ConnectionStatementResultSetなどのリソースを適切に解放することが重要です。リソースが解放されないと、メモリリークやデータベース接続の枯渇を引き起こす可能性があります。try-with-resources構文を使用することで、リソースの解放を自動化することができます。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class JDBCResourceExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/mydatabase";
        String username = "root";
        String password = "password";

        try (Connection connection = DriverManager.getConnection(url, username, password);
             Statement statement = connection.createStatement();
             ResultSet resultSet = statement.executeQuery("SELECT id, name, age FROM users")) {

            while (resultSet.next()) {
                int id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                int age = resultSet.getInt("age");
                System.out.println("ID: " + id + ", Name: " + name + ", Age: " + age);
            }
        } catch (SQLException e) {
            System.out.println("データベース操作中にエラーが発生しました。");
            e.printStackTrace();
        }
    }
}

5.2 接続プーリング

[編集]

データベース接続の作成と破棄はコストが高い操作です。接続プーリングを使用することで、接続を再利用し、アプリケーションのパフォーマンスを向上させることができます。HikariCPApache DBCPなどのライブラリを使用して、接続プーリングを実装することができます。

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import java.sql.Connection;
import java.sql.SQLException;

public class JDBCConnectionPoolExample {
    public static void main(String[] args) {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:mysql://localhost:3306/mydatabase");
        config.setUsername("root");
        config.setPassword("password");

        try (HikariDataSource dataSource = new HikariDataSource(config);
             Connection connection = dataSource.getConnection()) {

            System.out.println("データベースに接続しました。");

            // データベース操作を行う
        } catch (SQLException e) {
            System.out.println("データベース接続中にエラーが発生しました。");
            e.printStackTrace();
        }
    }
}

おわりに

[編集]
Wikipedia
Wikipedia
ウィキペディアJava Database Connectivityの記事があります。

本ハンドブックでは、JDBCの基本的な使い方から高度な機能までを解説しました。JDBCは、Javaアプリケーションとデータベース間の通信を実現するための強力なツールです。適切に使用することで、効率的で安全なデータベース操作を行うことができます。今後の開発において、本ハンドブックが役立つことを願っています。