Shoeisha Technology Media

CodeZine(コードジン)

記事種別から探す

iBATISを使ったO/RマッピングによるDBアクセスの実例 2

検索結果のマッピングと動的SQLの記述方法

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2007/07/05 14:00

ダウンロード SampleiBATIS2.zip (10.4 KB)

iBATISはSQLを利用することに注力したフレームワークです。この記事は前稿「iBATISを使ったO/RマッピングによるDBアクセスの実例」の続編です。今回はSELECT文に注目し、検索結果のマッピングと動的SQLの記述方法について説明します。

目次

はじめに

 iBATISはSQLを利用することに注力したフレームワークです。高機能なO/Rマッピングフレームワークに比べて簡単に理解でき、レガシーなJDBC、ResultSetを使ったプログラミングから簡単に乗り換えられます。

 特にSQLを多用する人には使いやすいフレームワークです。

 この記事は前回の「iBATISを使ったO/RマッピングによるDBアクセスの実例」の続編です。前回はSELECT、INSERT、UPDATE、DELETEの基本的な記述方法についてサンプルを紹介しました。今回はSELECT文に注目し、検索結果のマッピングと動的SQLの記述方法について説明します。

 iBATISの基本的な内容は、前回の記事を参考にしていただけると、分かりやすいと思います。

対象読者

  • Javaの基本をマスターしている人
  • SQL文を理解している人

必要な環境

 iBATIS 2.3.0、J2SE 5.0の環境を前提に解説しています。データベースの選択は自由ですが、サンプルプログラムはHSQLDBで動作確認しています。

サンプルデータベース

 本記事で使用しているデータベースは1つのテーブルを使用しています。

サンプルで利用するテーブル
CREATE TABLE EMP (
    EMPNO       NUMERIC(4) NOT NULL,
    ENAME       VARCHAR(10),
    JOB         VARCHAR(9),
    MGR         NUMERIC(4),
    HIREDATE    DATE,
    SAL         NUMERIC(7,2),
    COMM        NUMERIC(7,2),
    DEPTNO      NUMERIC(2) NOT NULL,
    CONSTRAINT PK_EMP PRIMARY KEY (EMPNO)
);

検索結果を格納するクラス

 検索結果を格納するBeanをあらかじめ用意しておきます。

Emp.javaの抜粋
package examples.dto;
import java.sql.Date;
public class Emp {
    private int empno;
    private String ename;
    private String job;
    private String manager;
    private Date hiredate;
    private float salary;
    private float commission;
    private int deptno;

    public int getEmpno() {
        return empno;
    }
    public void setEmpno(int empno) {
        this.empno = empno;
    }

    /* 中略 */
}

検索結果のマッピング

 SQLを実行した結果は、そのままでは格納先のBeanにきちんと格納できないことがあります。例えば、検索結果の列名とBeanのプロパティ名が異なる場合には、「検索結果のfoo列をBeanのbarプロパティに格納する」というマッピングが必要になります。

 また、「検索結果の値がNULL値のときは、Beanに999という値で格納する」という、ちょっとした条件判断によるマッピングが欲しい時もあります。

 今回紹介するサンプルでは、表1のように検索結果からBeanのプロパティへのマッピングを行います。

表1
検索結果の列格納先Beanのプロパティ備考
MGRmanager(String)
SALsalary(float)
COMMcommission(float)NULLのときは0.0を格納

 commissionプロパティはfloatで定義しているため、COMM列のデータがnullの場合は、0.0を格納する仕様とします。

SqlMap(SQLによるマッピング)

 一番簡単な例は、SQL文でマッピングしてしまう方法です。SqlMapは次のようになります。

 SQL文の別名とSQL関数を使ってマッピングします。

SqlMap-Emp.xmlの抜粋
<!-- SQLでマッピングする記述方法。ifnullはDBMSの関数 -->
<select id="allEmp1" resultClass="examples.dto.Emp">
    SELECT
        EMPNO,
        ENAME,
        JOB,
        MGR                as manager,
        HIREDATE,
        SAL                as salary,
        ifnull(COMM, 0.0)  as commission,
        DEPTNO
    FROM EMP
</select>

 SQLに慣れている場合はこの方法が直感的です。しかしSQL関数はRDBMSに依存した関数であるため、今回のサンプルの場合はHSQLDBに依存した書き方になってしまいます。

 次に説明するresultMap要素を使って記述すると、RDBMSに依存せずに記述することが可能です。

SqlMap(iBATISのresultMapによるマッピング)

 resultMap要素の記述で、検索結果→Beanのプロパティをマッピングします。

SqlMap-Emp.xmlの抜粋
<!-- resultMapを記述してIBATISの機能でマッピングする方法DBに
     依存しない記述 -->
<resultMap id="rm1" class="examples.dto.Emp">
    <result column="EMPNO" property="empno"/>
    <result column="ENAME" property="ename"/>
    <result column="JOB" property="job"/>
    <result column="MGR" property="manager"/>
    <result column="HIREDATE" property="hiredate"/>
    <result column="SAL" property="salary"/>
    <result column="COMM" property="commission" nullValue="0.0"/>
        <!-- NULLの時の指定 -->
    <result column="DEPTNO" property="deptno"/>
</resultMap>
<select id="allEmp2" resultMap="rm1">
    SELECT * FROM EMP
</select>

 resultMapは検索結果とJavaBeanをマッピングする定義です。この定義に"rm1"というIDを割り当てます。

 EMPNO列をempnoプロパティへ、...MGR列をmanagerプロパティへとマッピングしています。またnullValue属性で値を指定することで、NULL値の場合に格納する値を指定できます。

 記述量は増えてしまいますが、特に難しい記述ではありません。<select id="allEmp2">でのSELECT定義は、resultMap="rm1"を参照しています。

実行プログラム

 動作確認するサンプルは、次のようになります。

 両方のマッピング方法で同じ結果が得られることが確認できます。

Sample08_ResultMap.javaの抜粋
SqlMapClient sqlMap = MyAppSqlConfig.getSqlMapInstance();
/*
 * SQL文でマッピングに合うように結果を取得する。
 * ・列名はasでDTOに合うように
 * ・null値は0に変換して取得
 */
System.out.println("DBMSの関数ifnullを使用");
List<Emp> list1 = (List<Emp>)sqlMap.queryForList("allEmp1");
for (Emp e : list1){
    System.out.println(e);
}
/*
 * iBATISのResultMapでマッピングする
 */
System.out.println("ResultMapを使ってibatisでマッピング");
List<Emp> list2 = (List<Emp>)sqlMap.queryForList("allEmp2");
for (Emp e : list2){
    System.out.println(e);
}

  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

バックナンバー

連載:iBATISを使ったO/RマッピングによるDBアクセスの実例
All contents copyright © 2005-2017 Shoeisha Co., Ltd. All rights reserved. ver.1.5