Java Database Connectivity (JDBC) の詳細解説

JDBCの基礎概念

データベース連携を実装する際、JDBC(Java Database Connectivity)はJavaアプリケーションとリレーショナルデータベース間の標準インタフェースです。このAPIはSQL文の実行を可能にし、データベースベンダーが実装するドライバを通じて動作します。

基本操作フロー

  1. ドライバ導入: プロジェクトにデータベース固有のJDBCドライバを追加
  2. ドライバ登録: DriverManagerに使用するデータベースドライバを登録
  3. 接続確立: データベースへの接続オブジェクトを生成
  4. 操作実行: SQLクエリや更新処理の実施
  5. 結果処理: クエリ結果セットまたは更新件数の取得
  6. リソース解放: 接続やステートメントのクローズ処理

Statementによるデータ操作

静的SQL文を実行する際に使用します。以下はユーザーデータ取得の実装例です。

<!-- pom.xml依存関係 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.12</version>
</dependency>
import java.sql.*;

public class JdbcStatementExample {
    public static void main(String[] args) {
        Connection dbConnection = null;
        Statement sqlStatement = null;
        ResultSet queryResult = null;
        
        try {
            DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
            dbConnection = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/sampledb?useSSL=false",
                "dbuser", "password"
            );
            
            sqlStatement = dbConnection.createStatement();
            queryResult = sqlStatement.executeQuery("SELECT * FROM user_account");
            
            while(queryResult.next()) {
                System.out.println(
                    "ユーザー名:" + queryResult.getString("user_name") +
                    " 年齢:" + queryResult.getInt("age") +
                    " 残高:" + queryResult.getDouble("balance")
                );
            }
        } catch(SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if(queryResult != null) queryResult.close();
                if(sqlStatement != null) sqlStatement.close();
                if(dbConnection != null) dbConnection.close();
            } catch(SQLException ex) {
                ex.printStackTrace();
            }
        }
    }
}

PreparedStatementによる安全な操作

パラメータ化クエリを使用することでSQLインジェクションを防止します。自動生成キーの取得例:

public class PreparedStatementExample {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet keys = null;
        
        try {
            // 接続処理(省略)
            String insertSQL = "INSERT INTO user_account (user_name, age, balance) VALUES (?, ?, ?)";
            pstmt = conn.prepareStatement(insertSQL, Statement.RETURN_GENERATED_KEYS);
            
            pstmt.setString(1, "新規ユーザー");
            pstmt.setInt(2, 30);
            pstmt.setDouble(3, 500.0);
            
            int affectedRows = pstmt.executeUpdate();
            if(affectedRows > 0) {
                keys = pstmt.getGeneratedKeys();
                if(keys.next()) {
                    System.out.println("生成ID: " + keys.getInt(1));
                }
            }
        } catch(SQLException e) {
            e.printStackTrace();
        } finally {
            // リソース解放(省略)
        }
    }
}

ストアドプロシージャの実行

CallableStatementを使用したストアドプロシージャ呼び出しの例:

public class StoredProcedureExample {
    public static void main(String[] args) {
        Connection conn = null;
        CallableStatement cstmt = null;
        ResultSet rs = null;
        
        try {
            // 接続処理(省略)
            cstmt = conn.prepareCall("{call get_users_by_age(?, ?)}");
            cstmt.setInt(1, 25);
            cstmt.registerOutParameter(2, Types.INTEGER);
            
            rs = cstmt.executeQuery();
            while(rs.next()) {
                // 結果処理
            }
            System.out.println("該当件数: " + cstmt.getInt(2));
        } catch(SQLException e) {
            e.printStackTrace();
        } finally {
            // リソース解放(省略)
        }
    }
}

バッチ処理の最適化

複数の更新処理をまとめて実行する手法:

public class BatchProcessingExample {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        
        try {
            // 接続処理(省略)
            String sql = "INSERT INTO user_account (user_name, age, balance) VALUES (?, ?, ?)";
            pstmt = conn.prepareStatement(sql);
            
            for(int i=0; i<100; i++) {
                pstmt.setString(1, "ユーザー" + i);
                pstmt.setInt(2, 20 + i);
                pstmt.setDouble(3, 1000.0 + i);
                pstmt.addBatch();
            }
            
            int[] results = pstmt.executeBatch();
            System.out.println("処理件数: " + results.length);
        } catch(SQLException e) {
            e.printStackTrace();
        } finally {
            // リソース解放(省略)
        }
    }
}

トランザクション管理

ACID特性を保証する取引処理の実装:

public class TransactionExample {
    public static void main(String[] args) {
        Connection conn = null;
        try {
            // 接続処理(省略)
            conn.setAutoCommit(false);
            
            // 送金処理1: 口座Aから200円引き落とし
            // 送金処理2: 口座Bに200円入金
            
            conn.commit();
        } catch(Exception e) {
            try {
                if(conn != null) conn.rollback();
            } catch(SQLException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            // リソース解放(省略)
        }
    }
}

タグ: JDBC Java MySQL データベース SQL

5月21日 11:52 投稿