JDBCとは何か?
JDBC (Java Database Connectivity) は、Javaアプリケーションからデータベースにアクセスするための標準APIです。
JDBCを使用すると、データベースの種類に依存せず、一貫した方法でデータの操作が可能になります。
JDBCの主な特徴
- 異なるデータベースに対する統一的なアクセス方法を提供
- SQL文を使用したデータ操作をサポート
- トランザクション管理機能を提供
- Java SE標準ライブラリに含まれている
JDBCはODBCをベースに設計されていますが、Java固有の機能を多く持っています。
JDBCアーキテクチャ
JDBCの4つの主要コンポーネント
アプリケーション
JDBC API
JDBCドライバ
データベース
JDBCドライバのタイプ
- Type 1: JDBC-ODBC ブリッジドライバ (非推奨)
- Type 2: ネイティブAPIドライバ
- Type 3: ネットワークプロトコルドライバ
- Type 4: 純粋Javaドライバ(最も推奨)
プロジェクトでは通常、Type 4ドライバを使用することをお勧めします。これは純粋なJavaで書かれており、パフォーマンスが最も優れています。
基本的なJDBC操作の流れ
- JDBCドライバの登録
- データベース接続の確立
- Statementオブジェクトの作成
- SQLクエリの実行
- 結果の処理
- リソースのクローズ
// 1. JDBCドライバの登録 Class.forName("com.mysql.cj.jdbc.Driver"); // 2. データベース接続の確立 Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/mydb", "username", "password"); // 3. Statementオブジェクトの作成 Statement stmt = conn.createStatement(); // 4. SQLクエリの実行 ResultSet rs = stmt.executeQuery("SELECT * FROM users"); // 5. 結果の処理 while (rs.next()) { String name = rs.getString("name"); int age = rs.getInt("age"); System.out.println(name + ": " + age); } // 6. リソースのクローズ rs.close(); stmt.close(); conn.close();
JDBCの主要クラスとインターフェース
接続関連
- DriverManager: データベース接続を管理
- Connection: データベースへの接続を表現
ステートメント関連
- Statement: 単純なSQL文を実行
- PreparedStatement: 事前コンパイルされたSQL文(推奨)
- CallableStatement: ストアドプロシージャ呼び出し用
結果関連
- ResultSet: クエリ結果を保持するテーブル
- ResultSetMetaData: 結果セットに関するメタデータ
セキュリティのため、StatementよりもPreparedStatementを使用するべきです。SQLインジェクション攻撃を防ぐことができます。
PreparedStatementの使い方
PreparedStatementを使用すると、パラメータ化されたクエリが使用でき、SQLインジェクション攻撃を防ぎます。
// PreparedStatementの作成 String sql = "INSERT INTO users (name, age) VALUES (?, ?)"; PreparedStatement pstmt = conn.prepareStatement(sql); // パラメータの設定 pstmt.setString(1, "田中太郎"); // 1番目の?にセット pstmt.setInt(2, 30); // 2番目の?にセット // 実行 int rowsAffected = pstmt.executeUpdate();
メリット
- SQLインジェクション攻撃を防止
- クエリのパフォーマンスが向上(事前コンパイル)
- バイナリデータを扱いやすい
トランザクション管理
複数のデータベース操作をひとつの論理的な単位として扱います。
Connection conn = null; try { conn = DriverManager.getConnection(url, user, password); // 自動コミットを無効化 conn.setAutoCommit(false); // トランザクション内の処理 Statement stmt = conn.createStatement(); stmt.executeUpdate("UPDATE accounts SET balance = balance - 1000 WHERE id = 1"); stmt.executeUpdate("UPDATE accounts SET balance = balance + 1000 WHERE id = 2"); // 全ての操作が成功したらコミット conn.commit(); } catch (SQLException e) { // エラーが発生したらロールバック if (conn != null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } e.printStackTrace(); } finally { // リソースの解放 if (conn != null) { try { conn.setAutoCommit(true); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
トランザクションはACID特性(原子性、一貫性、独立性、耐久性)を満たすべきです。
JDBCベストプラクティス
コネクションプール
- データベース接続の作成コストを削減
- HikariCP、Apache DBCPなどのライブラリを活用
例外処理
- try-with-resourcesを使用したリソース管理
- SQLExceptionを適切に処理
セキュリティ
- 接続情報を外部設定ファイルに保存
- SQLインジェクション対策としてPreparedStatementを使用
// try-with-resourcesを使用した例 try ( Connection conn = DriverManager.getConnection(url, user, password); PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users WHERE id = ?") ) { pstmt.setInt(1, userId); try (ResultSet rs = pstmt.executeQuery()) { while (rs.next()) { // 結果の処理 } } } catch (SQLException e) { e.printStackTrace(); }