リレーショナルデータベースを利用する方法の一つに、JDBC APIがあります。最近の流行は多層C/Sシステム(Webアプリケーション等)なのでJDBCをクライアントで直接利用することは少ないかもしれません。しかし、SQL文を直接記述して発行することができるなど、使い道が広いAPIです。また、J2SEだけでプログラミングができます。
ではまず簡単なサンプルを作ってみましょう。簡単なサンプルといっても、よくあるJDBCでRDBMSに接続して簡単なテーブルをコンソールに表示するサンプルではおもしろくないです。ここでは、Javaの標準GUIライブラリであるSwingの表部品JTableに表示させてみましょう。
ファイル名 | 概要 |
---|---|
Main.java | プログラムのエントリ。コマンドライン解析と初期化を行う |
JdbcTableModel.java | 表示に対するモデルおよびRDBMSへの接続・検索を行う |
TableView.java | JdbcTableModelの内容を表示およびRDBMSへの問合せ指示のUIを持つ |
Can not access : file:/e:/home/toru/study/javaw/jdbc/ex3/Main.java
Can not access : file:/e:/home/toru/study/javaw/jdbc/ex3/JdbcTableModel.java
Can not access : file:/e:/home/toru/study/javaw/jdbc/ex3/TableView.java
JDBCはインタフェースに対してプログラミングを行うため、実際に接続するRDBMSの種類が何であろうとプログラムコードを変更する必要はありません。しかし、プログラムを実行する際に1個所だけ使用するJDBCドライバ名を記述しなくてはなりません。今までのサンプルコードでは大抵Class.forName("oracle.jdbc.driver.OracleDriver")のようにプログラム中にドライバ名をハードコーディングしていました。しかし、それではドライバを変更する度にプログラムを修正することになるため、ここではシステム・プロパティを使用してドライバ名を指定します。
D:\work>java -Djdbc.drivers=gwe.sql.gweMysqlDriver -cp \ .;d:\java\gwejdbc\gweMysql.jar Main \ "jdbc:mysql://localhost:3306/test?characterEncoding=SJIS" \ scott tiger
JDBC 2.0では、javax.sql.DataSourceインタフェースが追加されています。JNDIを使って、InitialContextからlookupメソッドによりDataSourceオブジェクトを検索します。DataSourceインタフェースのgetConnectionメソッドによってコネクションを確立することができます。JDBCドライバ名などは、JNDIによって外部で定義することになります。
JDBCではデータベースへ問い合わせを行うには、先に接続を行っておく必要があります。接続には、URL形式によるデータベースの指定、および接続の際に使用するユーザ名、パスワードを指定します。Statementは、SQL文を扱うクラスで、Connectionオブジェクトから生成します。
try { connection = DriverManager.getConnection(url, user, password); statement = connection.createStatement(); } catch (SQLException e) { :
SQL文はあらかじめStringとして作っておき、Statementオブジェクトのメソッドの1つを呼び出します。このとき、SQL文の種類によって呼び出すメソッドが変わります。問い合わせ文(SELECT)のときは、executeQueryです。実行結果は、ResultSetオブジェクトとして得られます。
String query = "SELECT * from " + tableName; try { ResultSet resultSet = statement.executeQuery(query); } catch (SQLException e) { :
実行結果であるResultSetオブジェクトから、列数、列の名前といったテーブル情報を取得します。getMetaDataメソッドを呼んでResultSetMetaDataオブジェクトを取り出します。列数は、ResultSetMetaDataオブジェクトのgetColumnCountメソッドを呼びます。列名は、ResultSetMetaDataオブジェクトのgetColumnNameメソッドを呼びます。getColumnNameメソッドは引数にインデックスとして列番号を指定しますが、SQLの世界ではインデックス番号は1から開始します。Javaの配列やコレクションの世界ではインデックス番号は0から開始するので、間違い易いです。
ResultSetMetaData metaData = resultSet.getMetaData(); columnCount = metaData.getColumnCount(); for (int i=0; i<columnCount; i++) { columnNames.add(metaData.getColumnName(i+1)); }
問い合わせSQL文の結果はResultSetオブジェクトに収められています。ResultSetは、コレクションにおけるイテレータのような振舞いをします。多くの場合、while文でループさせて個々のレコードにアクセスします。今回は、列番号を指定して値を取り出しています。値を取り出すときは、列の型によってそれぞれ専用のメソッドが用意されています。しかし、今回は文字列として値を取り出せればよいため全てgetStringメソッドを適用しています。ここでも列番号のインデックスは1から開始されます。
while (resultSet.next()) { String[] record = new String[columnCount]; for (int i=0; i<columnCount; i++) { record[i] = resultSet.getString(i+1); } records.add(record); rowCount++; }