DbUtilsで結果セットをJavaBeansにマッピングする
WINGSプロジェクト
BULL
2004/11/17
■基本的なデータベースアクセス方法の問題
Javaから一般的なリレーショナルデータベース(以下、データベースと呼称)にアクセスするには、以下に示すようにjava.sqlパッケージのConnection、Statement、ResultSetを使うのが基本です。
InitialContext init = new InitialContext( );
DataSource ds = (DataSource)init.lookup("java:comp/env/jdbc/TestDB");
Connection con = ds.getConnection();
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select * from items;");
…… // rsから結果を取得
rs.close(); // 終了処理
st.close(); // 終了処理
con.close();// 終了処理
init.close();// 終了処理
この基本的な方法では、以下のような問題があります。
リソースリークを防ぐため、毎回決まりきった終了処理コードを記述しなければならない
例外発生時にも終了処理コードが必ず実行されるように考慮しないといけない
このように、従来の方法ではコードの記述量が多く、記述方法にも気を使わなければいけませんでした。この問題は、Jakarta DbUtilsを使うことで解決できます。
■DbUtilsの概要
DbUtilsはJakarta Commonsプロジェクトの産物であり、Javaからデータベースにアクセスするためのツールです。DbUtilsはデータベースアクセスの基本的なAPIであるConnection、Statement、ResultSetを使用することによるコード記述の煩雑性を緩和し、かつ高速に動作することを目的として開発されました。DbUtilsはこれら基本的なAPIの代わりとして使用します。
DbUtilsの使い方の基本は以下のとおりです。QueryRunner#queryの戻り値がデータベース検索の結果になりますが、QueryRunner#queryの第2引数として渡すResultSetHandlerの内容により、QueryRunner#queryの戻り値の型が変化します。
import org.apache.commons.dbutils.QueryRunner;
importorg.apache.commons.dbutils.ResultSetHandler;
//中略
DataSource ds = ……
//JNDI等を用いて取得
QueryRunner qr = new QueryRunner(ds);
ResultSetHandler rsh = ……
//ResultSetHandlerの継承クラスのインスタンス
戻り値の型 result = (戻り値の型 )qr.query("SELECT ...", rsh);
DbUtilsのダウンロードはhttp://jakarta.apache.org/commons/dbutils/downloads.html からできます。執筆時点の最新版はバージョン1.0です。ダウンロードしたzipファイルを展開して出てきたcommons-dbutils-1.0.jarをクラスパスに通すことでjavaコードから使用可能になります。
■DbUtilsで結果セットをJavaBeansにマッピングする
DbUtilsでは、QueryRunner#queryの第2引数として、org.apache.commons.dbutils.handlersパッケージのBeanHandlerまたはBeanListHandlerのインスタンスを渡すことで、データベースを検索した結果セットを自動的にJavaBeansにマッピングすることができます。これを利用するとさらにコードの記述量を削減することができます。BeanHandlerとBeanListHandlerの違いは以下のとおりです。
BeanHandlerとBeanListHandlerの違い
DbUtilsのクラス
機能
QueryRunner#query
の戻り値の型
BeanHandler
最初のレコードのデータを、コンストラクタの引数に渡したJavaBeansクラスのインスタンスに格納し取得する
コンストラクタの引数に渡したJavaBeansクラス
BeanListHandler
BeansHandlerの全レコード対応版。全レコードについてBeanHandlerを適用し、得られた全JavaBeansインスタンスをListとして取得する
List(個々の要素はコンストラクタの引数に渡したJavaBeansクラスのインスタンス)
BeanHandlerまたはBeanListHandlerを用いて、データベースを検索した結果セットをJavaBeansにマッピングするには、データベースのテーブルのカラムとJavaBeansのプロパティとの間で型と名前(大文字小文字は同一視される)をそろえておく必要があります。例えばItems.sqlで定義されるテーブルITEMSに格納されるデータをJavaBeansにマッピングするには、MyBean.javaのようにJavaBeansを定義します。
Items.sql
CREATE TABLE ITEMS
( ID INTEGER PRIMARY KEY,
NAME VARCHAR(255) NOT NULL
);
MyBean.java
package mybean;
public class MyBean {
private int id;
private String name;
public void setId(int id) { this.id = id; }
public int getId() { return id; }
public void setName(String name) { this.name = name; }
public String getName() { return name; }
}
BeanListHandlerを使用して、データベースにアクセスし、テーブルITEMSに格納されている全データをMyBean.javaにより定義されるJavaBeansとして取得するjspの例をBeanListHandlerSample.jspとして示します。なお、前述したMyBean.javaのクラスファイルを含んだjarファイルと、DbUtilsのcommons-dbutils-1.0.jarがtomcat上のアプリケーションから参照可能になっており、DataSourceはJNDI名「java:comp/env/jdbc/TestDB」で取得できるものとします。tomcatでJNDI名を設定する方法は、「JNDI活用でデータソース管理を一元化する」 を参照してください。
BeanListHandlerSample.jspを見ると分かるように、わずか3行で目的の処理ができています。終了処理もInitialContextだけであり、コードもすっきりしているのが分かります。
BeanListHandlerSample.jsp
<%@ page contentType="text/html; charset=Windows-31J"
import="java.util.List,
java.util.Iterator,
javax.naming.InitialContext,
javax.sql.DataSource,
javax.naming.Context,
org.apache.commons.dbutils.QueryRunner,
org.apache.commons.dbutils.handlers.BeanListHandler,
org.apache.commons.dbutils.ResultSetHandler,
mybean.MyBean" %>
<%
InitialContext init = new InitialContext();
DataSource ds = (DataSource)init.lookup("java:comp/env/jdbc/TestDB");
QueryRunner qr = new QueryRunner(ds);
ResultSetHandler rsh = new BeanListHandler(MyBean.class);//結果を格納するJavaBeansを指定
//SQLを実行し、結果の各行に対応するMyBeanインスタンスを生成して各カラムの値をセットし、リストとして返す
List list = (List)qr.query("SELECT * FROM ITEMS", rsh);
%>
<html>
<head><title>DbUtils BeanListHandler sample</title></head>
<body>
<table border>
<tr><th>ID</th><th>Name</th></tr>
<%
for (Iterator i = list.iterator(); i.hasNext(); ) {
MyBean bean = (MyBean)i.next();
%>
<tr><td><%= bean.getId() %></td>
<td><%= bean.getName() %></td></tr>
<%
}
init.close();
%>
</table>
</body>
</html>
実行結果
TechTargetジャパン
キャリアアップ
**先週の人気講座ランキング**
〜 Android編 〜