2. データベース
2006.12.12 株式会社四次元データ 鈴木 圭
- 2.1. Java DB(Apache Derby)の標準バンドル
- 2.2. JDBC ドライバの自動ロード
- 2.3. 階層化された例外
- 2.4. Wrapper インタフェース
- 2.5. Ease of Development
- 2.6. サンプル・プログラム
Mustang では JDBC のバージョンが 4.0 にアップデートされました。JDBC 4.0 は SQL 2003 に対応しており、NCLOB(National Character Large Object)や ROWID などのデータ型に対応しています。また、Java DB(Apache Derby)が JDK に標準バンドルされたことにより、Java SE 環境でもデータベースを手軽に利用することができます。他にも、EoD(Ease of Development)の一環としてアノテーションの導入が行われ、PreparedStatement を直接扱うプログラムよりもコード量を削減することができます。
2.1. Java DB(Apache Derby)の標準バンドル
Java DB とは、オープンソースで開発されているリレーショナル・データベース Apache Derby を基にした Sun のディストリビューションです。100% Java で記述されていることや、アプリケーションに組み込んで使用できることなどの特徴を持ちます。Java DB のファイルは(JDK をインストールしたディレクトリを JAVA_HOME とすると)JAVA_HOME/db ディレクトリに配置されています。ただし、使用に関しては以下の点に注意する必要があります:
- バンドルされるのは Java DB 10.2 Alpha バージョン
- Alpha バージョンで作成されたデータベースは正規リリース版へのアップグレードは行えない
- バンドルされるのは JDK だけであり JRE には付属しない
色々と制限はありますが、JDBC 4.0 の新機能を試してみる場合などには便利です。
2.2. JDBC ドライバの自動ロード
JDBC 4.0 以前 | JDBC 4.0 |
---|---|
Class.forName("..."); ... Connection connection = DriverManager.getConnection(...); |
Connection connection = DriverManager.getConnection(...); |
コネクションを得る前に Class#forName メソッドによってドライバ・クラスをロードする処理が不要となります。JDBC 4.0 で追加されたドライバの自動ロード機能により、クラスパスに含まれるドライバ・クラスは自動的に検出、ロードされます。
2.3. 階層化された例外
以前のバージョンの JDBC はエラーを知らせるための例外の種類に乏しく、詳細なエラーの原因を知ることが困難でした。JDBC 4.0 では例外チェイン及び例外クラスのカテゴリ分けに改善が行われ、以前より詳細なエラー・ハンドリングが可能となりました。
例外チェインに関しては、今までも getNextException/setNextException というメソッドでサポートされていましたが、Throwable を受け取るコンストラクタが新しく追加されました。また、SQLException が Iterable を実装したことにより、foreach 構文でネストされた例外を辿ることができるようになりました。
例外クラスのカテゴリ分けに関しては、以下のように細かく分類されました:
- java.lang.Throwable (implements java.io.Serializable)
- java.lang.Exception
- java.lang.RuntimeException
- java.sql.SQLRuntimeException
- ...
- java.sql.SQLRuntimeException
- java.lang.RuntimeException
- java.sql.SQLException (implements java.lang.Iterable<T>)
- java.sql.BatchUpdateException
- java.sql.SQLClientInfoException
- java.sql.SQLNonTransientException
- ...
- java.sql.SQLRecoverableException
- java.sql.SQLTransientException
- ...
- java.sql.SQLWarning
- ...
- java.lang.Exception
まず、RuntimeException のサブクラスとして SQLRuntimeException が新しく追加されました。SQLRuntimeException は JDBC 4.0 で追加された EoD(Ease of Development)に関する処理で発生したエラーを表す例外です。SQLException のサブクラスには、新しく SQLClientInfoException、SQLNonTransientException、SQLRecoverableException、SQLTransientException が追加されました。
SQLClientInfoException はクライアント情報の設定に失敗した場合、SQLRecoverableException は何らかのリカバリ処理を行った後に同じオペレーションを実行すれば処理が成功するかもしれない場合に投げられます。また、エラーが一時的(再び実行すれば成功する可能性がある)か、そうではないか、という分類も行われました。SQLTransientException は処理がタイムアウトした場合など、エラーとなったオペレーションを再度実行すると成功するかもしれない場合に投げられる例外です。SQLNonTransientException は発行した SQL クエリに構文エラーがある場合など、同じオペレーションを何度実行してもエラーとなる場合に投げられます。
SQLWarning は以前から存在するクラスで、例外よりは軽度の「警告」を表すものです。SQLWarning は他の例外のように throw されるわけではなく、Connection や Statement、ResultSet の getWarnings メソッドで明示的に取得します。
2.4. Wrapper インタフェース
JDBC は Java におけるデータベース・アクセスを抽象化したものですが、JDBC の具体的な実装には JDBC で定義されているもの以外の独自機能を持つものがあります。java.sql.Wrapper インタフェースは、そのような JDBC 実装の独自機能にアクセスするための手段を提供するインタフェースです。Wrapper インタフェースは Connection や Statement、ResultSet、DataSource インタフェース(全て java.sql パッケージ)などが実装しています。通常は JDBC によって抽象化された機能だけを使用してプログラミングを行いますが、特定の JDBC 実装独自の機能を利用したい場合は Wrapper インタフェースを通して実装インスタンスを取得します。Wrapper インタフェースには以下に示すメソッドが含まれています:
- boolean isWrapperFor(Class<?> iface)
- iface に指定したクラスのラッパーである場合に true を返します。 - <T> T unwrap(Class<T> iface)
- ラップしている iface インスタンスを返します。
isWrapperFor メソッドは Wrapper が指定したクラスのラッパーであるか判別するために使用します。そして、unwrap メソッドによってラップされている実装インスタンスを取得します。以下に使用例を示します:
Connection connection = ...; Statement statement = connection.createStatement(); Class clazz = Class.forName("oracle.jdbc.OracleStatement"); if(statement.isWrapperFor(clazz)) { OracleStatement oracleStatement = statement.unwrap(clazz); ... }
2.5. Ease of Development
Mustang では EoD(Ease of Development)を促進するために、アノテーションの導入が行われました。導入されたアノテーションは以下の四種類です(全て java.sql パッケージ):
- Select
- 結果セットを返す SQL クエリ(SELECT 文)を指定するために使用します。 - Update
- 更新カウントを返す SQL クエリ(UPDATE 文)を指定するために使用します。 - ResultColumn
- 結果セットに含まれるカラムの名前からデータ・クラスのフィールドの名前のマッピングを指定するために使用します。 - AutoGeneratedKeys
- データ・クラスが自動生成されたキーを受け取るかどうか指定するために使用します。
また、アノテーションによって実行するクエリのインタフェースとなる java.sql.BaseQuery や、実行された SQL の結果セットを表す java.sql.DataSet<T> インタフェースなども追加されました。
従来の JDBC プログラミングでは java.sql.PreparedStatement を使用して SQL クエリを実行し、java.sql.ResultSet から返されたデータを取得していました。しかし、JDBC 4.0 の EoD 機能では、Tiger で導入されたアノテーションと Generics を利用することで、簡単かつタイプセーフに目的の処理を記述することを可能とします。
注意として、JDBC 4.0 の EoD 機能は OR マッピング(Object-Relational Mapping)を目的としたものではなく、PreparedStatement と ResultSet を使用する従来の JDBC プログラミングをより簡単にするための機能を提供する、という位置付けです。OR マッピングのためには Java Persistence API の利用が想定されています。
基本的な使い方
個々のアノテーションの説明に入る前に、説明で使用する用語の定義も兼ねて JDBC 4.0 の EoD 機能で登場するクラスやインタフェースの関連を説明します:
- アノテーション
- 上記の Select、Update、ResultColumn、AutoGeneratedKeys アノテーション。 - Query インタフェース
- アノテーションによって修飾された一連のメソッドを定義するインタフェース。BaseQuery インタフェースを継承して作成します。 - BaseQuery インタフェース
- 全ての Query インタフェースの親となるインタフェース。Query オブジェクトを閉じる close メソッドなどを定義します。 - DataSet<T> インタフェース
- Select アノテーションによって修飾された Query インタフェースのメソッドの戻り値。ResultSet の代わりとして、結果セットに対するタイプセーフなアクセスを提供します。 - データ・クラス
- 結果セットを受け取るためのクラス。DataSet<T> のパラメータ引数に与えます。
上のリストの中でプログラマが作成するのは「Query インタフェース」と「データ・クラス」の二つです。データ・クラスは、C 言語の構造体のようなスタイル(全てのフィールドが public)で作成するか、JavaBeans のプロパティ(Getter/Setter)スタイルで作成します。例として、人を表す Person クラスを構造体スタイルで作成すると、以下のようになります:
// 構造体スタイルのデータ・クラス public class Person { public int id; public String name; }
Query インタフェースは、BaseQuery インタフェースを必ず継承します:
public interface PersonQueries extends BaseQuery { @Select("SELECT * FROM Person") DataSet<Person> getAll(); @Update("UPDATE Person SET name=?2 WHERE id=?1") int setName(int id, String name); }
上記のように Query インタフェースには Select や Update アノテーションによって修飾したメソッドを定義します。Select や Update アノテーションの詳細は後述しますが、上のコードを見れば実行する SQL クエリを指定していることが分かると思います。作成した Query インタフェースの実装は、java.sql.Connection または javax.sql.DataSource インタフェースの createQueryObject メソッドによって作成することができます:
Connection connection; ... PersonQueries personQueries = connection.createQueryObject(PersonQueries.class);
Select アノテーションによって修飾されたメソッドを呼び出すことで、結果セットを DataSet<Person> として得ることができます:
DataSet<Person> persons = queries.getAll(); for(Person person : persons) { ... person の処理 }
このように、JDBC 4.0 の EoD 機能を利用すると、PreparedStatement や ResultSet を直接扱う場合と比べて、簡単かつタイプセーフに処理を行うことができます。
DataSet<T>
DataSet<T> は実行した SQL クエリの結果セットを表すインタフェースです。ResultSet に比べてタイプセーフであるという利点があります。
DataSet<T> を用いてデータの更新を行うには、modify、delete、insert メソッドによって行います。また、DataSet<T> には接続モードと非接続モードの二つのモードがあります。接続モードの場合、データの更新が即座に反映されますが、非接続モードの場合は DataSet#sync メソッドが呼び出されるまで更新が反映されません。DataSet<T> の接続/非接続モードの指定は Select アノテーションの connected パラメータによって行います。
Select アノテーション
Select アノテーションは、結果セットを返す SQL クエリ(SELECT 文)を指定するために使用します。結果セットを返さない SQL クエリを指定した場合は、実行時に SQLRuntimeException が投げられます。以下に Select アノテーションの使用例を示します:
interface PersonQueries extends BaseQuery { @Select("SELECT * FROM Person") public DataSet<Person> getAll(); @Select("SELECT * FROM Person WHERE name=?1") public DataSet<Person> findByName(String name); }
getAll メソッドを修飾するアノテーションには、Person テーブルの全てのレコードを返す SELECT 文を指定しています。一方、findByName メソッドを修飾するアノテーションにはパラメータ引数(「?1」)を含む SELECT 文を指定しています。パラメータ引数は PreparedStatement の場合と異なり、クエスチョン・マークに続けて数字(1 〜)を指定します。数字は、そのパラメータ引数にメソッドの何番目の引数が当てはめられるかを指定します(つまり「?1」はメソッドの一番目の引数がそこに当てはめられます)。また、パラメータ引数に値が当てはめられるときは PreparedStatement 同様、文字のエスケープ処理も行われます。
Select アノテーションには以下のパラメータを指定することができます:
型 | 名前 | 説明 | デフォルト |
---|---|---|---|
String | sql または value | 実行される SELECT 文。 | なし |
String | tableName | DataSet#sync メソッドの呼び出しによって更新されるテーブルの名前。 | なし |
boolean | readOnly | 返される DataSet<T> が読み取り専用であるかの指定。true の場合に読み取り専用となります。 | true |
boolean | connected | DataSet<T> がバックエンドのデータ・ソースと接続されるかの指定。true の場合に接続モードとなります。 | true |
boolean | allColumnsMapped | SQL クエリの実行結果のカラム名とデータ・クラスのフィールドが一対一対応であるかの指定。true の場合、一対一に対応しないデータは無視されるようになります。 | false |
boolean | scrollable | 接続モードの DataSet<T> をスクロール可能とするかどうかの指定。非接続モードの場合はこのパラメータは無視されます。 | false |
Select アノテーションを簡単に利用するだけならば実行する SQL クエリを指定するだけで良いのですが、これらのパラメータを使用することでメソッドから返される DataSet<T> の振る舞いをカスタマイズすることができます。
実行する SQL クエリは sql または value パラメータで指定します。メソッドから返される DataSet<> を読み取り専用(更新不可能)とするかどうかは readOnly パラメータで指定します。allColumnsMapped は結果セットのレコードがデータ・クラスのフィールドに一対一で対応すること指定するためのパラメータで、true を指定するとカラム名とフィールド名が一対一に対応しないデータは全て無視される(戻り値の DataSet<T> に含まれない)ようになります。
connected は DataSet<T> の接続/非接続モードを決めるためのパラメータであり、tableName、scrollable は DataSet<T> が非接続モードの場合に有効なパラメータです。connected が true の場合、メソッドから返される DataSet<T> は接続モードとなり、データの更新は即座に反映されます。一方、connected に false を指定した場合は非接続モードとなり、DataSet#sync メソッドが呼び出されるまで更新の反映は行われません。tableName には DataSet#sync メソッドが呼び出されるときに更新されるデータベースのテーブル名を指定します。scrollable は DataSet<T> をスクロール可能とするかどうかを指定するためのパラメータです。省略または true が指定されると、内部で作成される java.sql.Statement が java.sql.ResultSet.TYPE_SCROLL_INSENSITVE として作成されます。false の場合は内部で作成される Statement が ResultSet.TYPE_FORWARD_ONLY として作成します。
Update アノテーション
Update アノテーションは更新カウントを返す SQL クエリを(UPDATE や DELETE 文)を指定するために使用します。結果セットを返す SQL クエリを指定した場合は、実行時に SQLRuntimeException が投げられます。以下に使用例を示します:
interface PersonQueries extends BaseQuery { @Update("UPDATE Person SET age=?2 WHERE id=?1") public int setAge(int id, int age); @Update("DELETE FROM Person") public void deleteAll(); }
Update アノテーションでもパラメータ引数を使用することができます。setAge メソッドのアノテーションでは指定した id を持つレコードの age フィールドを指定した値に変更する SQL クエリを指定しています。setAge の戻り値は更新されたレコードの数を返します。deleteAll メソッドのアノテーションでは Person テーブルの全てのデータを削除する SQL クエリを指定しています。また、更新カウントは不要(という想定)のため、戻り値を void としています。Update アノテーションによって修飾されるメソッドの戻り値は、更新カウントが必要な場合は int、不要な場合は void とします。
Update アノテーションには以下のパラメータを指定することができます:
型 | 名前 | 説明 | デフォルト |
---|---|---|---|
String | sql または value | 実行される SQL クエリ(UPDATE や DELETE 文)。 | なし |
GeneratedKeys | keys | 自動生成されたキーが返されるかどうかの指定。 | GeneratedKeys.NO_KEYS_RETURNED |
実行する SQL クエリは sql または value パラメータで指定します。keys パラメータはクエリの実行結果として自動生成されたキーが返されるかどうかを指定するためのものです。詳しくは AutoGeneratedKeys アノテーションの項目手説明します。
ResultColumn アノテーション
ResultColumn アノテーションはデータ・クラスのフィールドに対して指定するアノテーションです。実行した SQL クエリの結果に含まれるカラム名とデータ・クラスのフィールド名が異なる場合に、そのマッピングを指定するために使用します。
例えば、実行したクエリの結果に含まれる name カラムの値をデータ・クラスの userName フィールドにマッピングしたい場合は、以下のように ResultColumn アノテーションを利用します:
public class Person { @ResultColumn("name") private String userName; ... }
ResultColumn アノテーションには、以下のパラメータを指定することができます:
型 | 名前 | 説明 | デフォルト |
---|---|---|---|
String | name または value | ResultSet のカラムの名前。 | なし |
boolean | uniqueIdentifier | 非接続モードの DataSet<T> でデータの修正が行われるときに、フィールドがレコードを一意に識別するために使用されるかどうかの指定。 | false |
SQL クエリの結果として返されるレコードのカラム名は name または value パラメータで指定します。このパラメータで指定したカラムの値が修飾されるフィールドにマッピングされます。uniqueIdentifier が true の場合は、非接続モードの DataSet<T> によってレコードが修正されるときに、修飾されるフィールドがレコードの一意識別子であるとみなされます。
ResultColumn と allColumnsMapped に関する問題
現状では Select アノテーションの allColumnsMapped に true を指定した場合、ResultColumn アノテーションによって修飾されたフィールドが正しく認識されないという問題があります(BUGID 6445325)。例えば、以下のようなデータ・クラスと Query インタフェースがある場合:
// データ・クラス public class Person { public int id; @ResultColumn("name") public String userName; }
// Query インタフェース public interface PersonQueries extends BaseQuery { @Select(sql="SELECT id, name FROM Person", allColumnsMapped=true) public DataSet<Person> getAll(); }
PersonQueries の getAll メソッドは空の DataSet<Person> が返されてしまいます。
AutoGeneratedKeys アノテーション
いくつかの RDBMS では、レコードを追加するときに特定のカラムの値を自動生成する機能を持ちます。例えば、MySQL では AUTO_INCREMENT という連番を自動的に生成する機能を持ちます。AutoGeneratedKeys は、RDBMS によって自動生成されたキーを受け取るためのクラスであることを指定するために使用するアノテーションです。
例えば、フィールドに id と name を持つ Person テーブルがあり、id フィールドの値が自動生成されるとします。その場合、自動生成されるキーを受け取るためのクラスは以下のように作成します:
@AutoGeneratedKeys public class PersonKeys { public int id; }
そして、Query インタフェースでは Update アノテーションの keys パラメータで自動生成されるキーが返されることを指定します:
public interface PersonQueries extends BaseQuery { @Update(sql="INSERT INTO Person (name) VALUES(?1)", keys=GeneratedKeys.RETURNED_KEYS_COLUMNS_SPECIFIED) public DataSet<PersonKeys> add(String name); }
Update アノテーションの keys パラメータは、実行したクエリが自動生成されたキーを返すかどうかを指定するためのものです。列挙型 java.sql.GeneratedKeys の値を指定します:
- GeneratedKeys.NO_KEYS_RETURNED
- 自動生成されたキーが返されないことを意味します。Statement.executeUpdate(String sql, Statement.NO_GENERATED_KEYS) と同じです。 - GeneratedKeys.RETURNED_KEYS_COLUMNS_SPECIFIED
- データ・クラス(上の例の場合は PersonKeys)のフィールド名によって返されるキーが決定されることを意味します。Statement.executeUpdate(String sql, String[] colNames) と同じです。 - GeneratedKeys.RETURNED_KEYS_DRIVER_DEFINED
- JDBC ドライバの判断によって自動生成されたキーが返されることを意味します。Statement.executeUpdate(String sql, Statement.RETURN_GENERATED_KEYS) と同じです。
keys パラメータのデフォルトでは自動生成されたキーが返されないことを意味する NO_KEYS_RETURNED なので、自動生成されたキーを取得したい場合は他の値を明示的に指定します。
2.6. サンプル・プログラム
最後に JDBC 4.0 の EoD 機能を利用したサンプル・プログラムを作成します。作成するプログラムでは、データ・クラスとして Person クラスを用意して、それをデータベースに対して挿入、削除、更新、選択という基本的な操作を行う Query インタフェース(PersonQueries)を作成します。それらを作成した後に、Query インタフェースを用いてデータベースに対してデータの追加や削除を行う動作確認用のプログラムを作成することとします。
データベースには標準バンドルされた Java DB(Apache Derby)を使用します。今回は他のプログラムにデータベースを公開する必要は無いので、データベースをアプリケーションに組み込んで動作させる形態で利用します。Java DB(Apache Derby)を利用するには JAVA_HOME/db/lib/derby.jar をクラスパスに追加する必要があります。
データ・クラス
データ・クラスとして 名前と年齢の二つの情報を持つ Person クラスを作成します。名前、年齢はそれぞれ name、age フィールドに保持します。ここでは JavaBeans スタイルではなく構造体スタイル(全てのフィールドが public)として作成します:
// Person.java public class Person { public String name; public int age; @Override public String toString() { return String.format("[name=%s, age=%d]", name, age); } }
Query インタフェース
次に Query インタフェースとして PersonQueries を作成します。PersonQueries には select、insert、update、delete メソッド(それぞれ SQL の SELECT 文、INSERT 文、UPDATE 文、DELETE 文に対応する)を定義することにします:
// PersonQueries.java import java.sql.BaseQuery; import java.sql.DataSet; import java.sql.Select; import java.sql.Update; public interface PersonQueries extends BaseQuery { @Select("SELECT name, age FROM Person") public DataSet<Person> select(); @Update("INSERT INTO Person (name, age) VALUES(?1, ?2)") public int insert(String name, int age); @Update("UPDATE Person SET age=?2 WHERE name=?1") public int update(String name, int age); @Update("DELETE FROM Person") public int delete(); }
select メソッドはテーブルに含まれる全てのレコードを DataSet<Person> として返します。insert メソッドは指定した名前、年齢のデータを挿入します。update メソッドは指定した名前を持つデータの年齢を設定します。delete メソッドはテーブルに含まれる全てのデータを削除します。
動作確認用プログラム
最後に、作成した PersonQueries を使用して動作確認用のプログラムを示します。プログラムを単純にするため、エラー処理は省略しています。
// SampleMain.java import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class SampleMain { private static final String DB_URL = "jdbc:derby:SampleDB;create=true"; public static void main(String[] arguments) throws SQLException { Connection connection = DriverManager.getConnection(DB_URL); createTable(connection); someProcess(connection); dropTable(connection); connection.close(); } private static void createTable(Connection connection) throws SQLException { System.out.println("--- createTable"); Statement statement = connection.createStatement(); statement.execute("CREATE TABLE Person (name VARCHAR(16), age INTEGER)"); statement.close(); } private static void dropTable(Connection connection) throws SQLException { System.out.println("--- dropTable"); Statement statement = connection.createStatement(); statement.execute("DROP TABLE Person"); statement.close(); } private static void someProcess(Connection connection) throws SQLException { PersonQueries queries = connection.createQueryObject(PersonQueries.class); System.out.println("--- insert"); queries.insert("太郎", 10); queries.insert("次郎", 20); queries.insert("花子", 30); System.out.println("--- select"); for(Person person : queries.select()) { System.out.println(person); } System.out.println("--- update"); queries.update("太郎", 30); queries.update("次郎", 20); queries.update("花子", 10); System.out.println("--- select"); for(Person person : queries.select()) { System.out.println(person); } System.out.println("--- delete"); queries.delete(); System.out.println("--- select"); for(Person person : queries.select()) { System.out.println(person); } queries.close(); } }
Java DB(Apache Derby)ではデータベースに接続するときの URL に "jdbc:derby:<データベース名>;[<オプション>]" という形式を使用します。上記コードでは URL に "jdbc:derby:SampleDB;create=true" としています。この場合、データベース名は "SampleDB" となります。また、オプションの "create=true" はデータベースが存在しない場合に自動的に作成させるためのものです。
処理の流れは、最初にテーブルを作成し、PersonQueries を用いた処理を行い、最後にテーブルを削除する、というものです。それぞれ createTable、someProcess、dropTable メソッドで処理を行っています。someProcess メソッドでは PersonQueries のメソッドを使用し、以下の処理を行っています:
- データを挿入(PersonQueries#insert)
- 挿入したデータを取得、表示(PersonQueries#select)
- データを更新(PersonQueries#update)
- 更新したデータを取得、表示(PersonQueries#select)
- メソッドで全てのデータを削除(PersonQueries#delete)
- 削除されたことを確認するためにデータを取得、表示(PersonQueries#select)
このプログラムを実行するときは、JAVA_HOME/db/lib/derby.jar をクラスパスに含めることを忘れないでください。
実行結果
このプログラムを実行すると、以下のような出力が得られます:
--- createTable --- insert --- select [name=太郎, age=10] [name=次郎, age=20] [name=花子, age=30] --- update --- select [name=太郎, age=30] [name=次郎, age=20] [name=花子, age=10] --- delete --- select --- dropTable
データの挿入(insert)、更新(update)、削除(delete)それぞれの直後に PersonQueries#select メソッドでデータを取得/表示していますが、出力から正しく処理が行われていることを確認できます。
サンプル・プログラムは以上です。作成したプログラムを振り返ると分かっていただけると思いますが、このプログラムの本質的な部分は Person クラスと PersonQueries インタフェースであり、どちらも非常に短く記述することができています。最後に作成した動作確認用のプログラムが一番長くなってしまったくらいです。このことだけでも EoD 機能の利点を十分に感じることができたのではないでしょうか。
まとめ
今回はデータベース関係の説明ということで、JDBC 4.0 の EoD 機能を中心に解説を行いました。JDBC 4.0 の EoD 機能を利用することで、以前の JDBC プログラミングのような PreparedStatement と ResultSet を使用したコーディングと比べて簡単かつ短い記述量で処理を記述できることが分かっていただけたと思います。今のところ JDBC 4.0 に対応した JDBC ドライバの実装は少ないですが、徐々に対応されていくと思われます。
さて次回は、システム・トレイやスプラッシュ・スクリーンのサポートなどの機能強化が行われたデスクトップ関係の機能について解説を行います。