はじめに
JavaのWebアプリケーションに,DBを利用した機能を実装するために必要となるJDBCについてまとめる.まずは,JDBCの概要をまとめてから,基本的な実装方法についてまとめる.
JDBCとは
JDBCは"Java DataBase Connectivity"の頭文字をとったもので,Javaプログラムがデータベース管理システムにアクセスできるようにするものである.
JDBCを構成する基本要素は以下の二つである.
1. JDBC API
Javaアプリケーションがデータベースにアクセスするためのクラス/インタフェースの集まりである.これらを用いて,データベースを操作するプログラムを作成する.
2. JDBCドライバマネージャー
複数のJDBCドライバを管理するためのクラスで,目的のデータベースに対応したJDBCドライバを選択し接続するために使用する.
3. JDBCドライバ
特定のデータベースシステムとの通信を可能にするJavaクラスの集合で,使用したいデータベースの種類(Oracle・MySQL・PostgreSQLなど)ごとに用意する必要がある.
JDBC APIとドライバマネジャーはJDKにすでに含まれているため,Javaアプリの開発環境が整っていれば準備できているはず.JDBCドライバは,データベースベンダーーが提供してくれるもので,Webサイトからダウンロードすることで用意する.
メリット
JDBCの大きなメリットは,使用するDBが異なっても,Javaのプログラムをほぼ変えなくてもいい という点である.
JDBCドライバはDBの操作を行うJavaプログラムを特定のデータベースシステム用に変換してくれる.そのため,使用するDBを変更する場合は,開発者はJDBC APIに沿った書き方さえ行えば,使用するDBごとのJDBCドライバを用意するだけで済む.
JDBCのイメージ
JDBCの実装方法
JDK(JDBC API)やJDBCドライバ,使用するDBのインストールなどの環境構築が終わっていることを前提に,実際にJavaプログラムからデータベースの操作を行うまでの流れをまとめる.ここでは例としてデータベースはMySQLを使うが,他のデータベースでもほぼ変わらない.
使用するクラス&インタフェース
Driver Managerクラス
→データベースへ接続するJDBCドライバの管理を行うために使用する
Connectionインタフェース
→データベースとの通信やトランザクション管理など,データベースへのアクセスのための基本的なメソッドを提供する
Statementインタフェース
→SQLクエリをデータベースに送信するために使用する.
ResultSetインタフェース
→データベースから取得した行と列を結果として保持する.アプリケーションではこれを使用してデータを取り出す.
SQLExceptionクラス
→データベースアクセス時に発生する時の例外処理を行うために使用する.
Javaプログラムで記述するJDBCの処理の流れ
MySQLを利用した時の例
//データベースの接続
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("url","username","password");
//データ操作の準備
String Query = "SQL文";
PreparedStatement statement = connection.prepareStatement(Query);
//データベースの操作
ResultSet resultSet = statement.executeQuery();
resultSet.getInt("id");
//リソースの解放
resultSet.close();
Statement.close();
connection.close();
JDBCの処理の流れは大きく分けると以下のようになる.
1.データベースへの接続
2.データ操作の準備
3.データの操作(追加・変更・削除)
4.リソースの解放
これらについてもう少し詳しくまとめる.
データベースへの接続
1.JDBCのインポート
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement; //または java.sql.PreparedStatement;
import java.sql.SQLException;
データベースとの接続・操作を行うために必要な上記の4つをインポートする.
Statementに関するインタフェースは,データベースの操作の実装によってインポートするものは変わる.
2.JDBCドライバのロード
Class.forName("com.mysql.jdbc.Driver");
Class.forName()
メソッドを利用して,データベースに対応するJDBCドライバを指定する.
MySQLの場合は,com.mysql.jdbc.Driver
を指定する.
3.Connectionオブジェクトの取得
Connection connection = DriverManager.getConnection("url","username","password");
DriverManager()
メソッドを利用して,Connectionオブジェクトを取得する.引数とは以下の3つを指定する.
- URL:データベースの場所を示すJDBCのURL
- ユーザ名:DB接続のユーザー名
- パスワード:DB接続する際のパスワード
データ操作の準備
データ操作の準備として,StatementオブジェクトまたはPreparedStatementオブジェクトの取得を行う.
実行するSQL文が静的・動的かによって使い分ける.
//静的 → Statement
Statement statement = connection.createStatement();
//動的 → PreparedStatement
String sql = "INSERT INTO my_table (column1, column2) VALUES (?, ?)";
PreparedStatement pstmt = connection.prepareStatement(sql);
PreparedStatementはあらかじめSQLクエリを用意しておき,SQLクエリ内のパラメータ(SQL文の?
)に何を入れるかを後で指定する.このように動的なSQLクエリを利用する場合は,PreparedStatementの方が適している.
また,外部データを直接組み込むStatementと比較すると,外部データをパラメータとして扱うPreparedStatementの方がセキュリティの観点から優れている.
データの操作
データの操作は基本的に"データの検索(参照)"と"データの更新(追加/更新/削除)"の2つを行う.
データ操作の準備でStatementかPreparedStatementを利用するかで方法が異なる.
Statement オブジェクトの場合
データの検索(参照)手順
1.SQLクエリの文字列を用意
String sql = "SELECT * FROM テーブル名";
検索にはSQL文のSELECTを利用して,何を検索するのかを指定する.(SQLの書き方には触れない.)
2.SQLクエリの実行
ResultSet result = statement.executeQuery(sql);
StatementオブジェクトのexecuteQuery
メソッドを利用して,クエリを実行する.引数にはSQLクエリの文字列を渡す.
結果としてResultSet
オブジェクトが返される.
3.データベースからの結果を取得
while(resultSet.next()) {
//例
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
print(id+":"+name);
}
結果として受け取ったResultSet
オブジェクトをnext()
メソッドを利用することで,取得したデータを1行ずつ取り出すことができる.
データの更新手順
1.SQLクエリの文字列を用意
String sql = "INSERT INTO テーブル名 (データラベル1, データラベル2) values (値1,値2)";
データの更新操作は挿入(INSERT)と更新(UPDATE)と削除(DELETE)の3つである.
2.SQLクエリの実行
statement.executeUpdate(sql);
StatementオブジェクトのexecuteUpdate
メソッドを利用する.引数には先ほど定義したSQLクエリの文字列を渡す.メソッドの返り値は実行されたクエリによって変更された行の数である.
PreparedStatement オブジェクトの場合
データの検索(参照)手順
1.SQLクエリ文字列を用意
String sql = "SELECT * FROM テーブル名 WHERE name = ?";
PreparedStatementの場合は,プレースホルダー?
を使用してクエリを準備する.
2.PreparedStatementオブジェクトの取得
PreparedStatement statement = connection.prepareStatement(query);
Statementと違い,PreparedStatementオブジェクトの取得はクエリを用意してから行う.connection.prepareStatement
メソッドの引数にクエリを渡し,PreparedStatementオブジェクトを取得する.
3.プレースホルダーの値を指定
statement.setString(1,"data");
取得したPreparedStatementオブジェクトのsetString
メソッドを利用して,クエリのプレースホルダーに値を指定する.第一引数となる番号は複数のプレースホルダーを利用した場合に,番号と位置を一致したものを指定する.
4.クエリの実行
ResultSet resultSet = statement.executeQuery();
statement.Query()
メソッドでクエリを実行する.クエリはすでにPreparedStatementオブジェクトに指定されているため,引数は必要ない.
resultSetからのデータの取得は,Statementの場合と同じである.
データの更新手順
1.SQLクエリ文字列を用意
String sql = "INSERT INTO テーブル名 (データラベル1, データラベル2) values (?,?)";
検索処理と同様に,PreparedStatementの場合は,プレースホルダー?
を使用してクエリを準備する.
2.PreparedStatementオブジェクトの取得
PreparedStatement statement = connection.prepareStatement(sql);
こちらも同様で,PreparedStatementオブジェクトの取得はクエリを用意してから行う.
3.プレースホルダーの値を指定
statement.setString(1,"data");
これも同様に,プレースホルダーに入れる値をsetString
メソッドで指定する.更新処理の場合は,実際にデータベースに入れる値が指定されることになる.
4.クエリの実行
ResultSet resultSet = statement.executeUpdate();
statement.Update()
メソッドでクエリを実行する.クエリはすでにPreparedStatementオブジェクトに指定されているため,引数は必要ない.
リソースの解放
resultSet.close();
statement.close();
connection.close();
データベースの操作を終えた後は,データベースの接続を明示的に切断する必要がある.close()
メソッドを利用してデータ操作を行うために取得したResultSet
オブジェクトとConnection
オブジェクト,Statment
オブジェクトを解放することで,データベースの接続を切断する.
まとめ
この記事では,JDBCの概要と基本的な実装方法についてまとめた.
JDBCだけでなく,データベースが使えるようになると,Web開発の幅が広がるため,使いこなせるようになりたい.