DBFlute を使ってみる

WEB+DB PRESS vol.41 を参考に、S2Dao のクラスを自動生成するツール DBFlute(0.5.6)を使ってみることにする。
WEB+DB PRESS Vol.41

手動で DBFlute インストール

はじめに、以下のプロジェクトを作成。

WEB+DB PRESS では自動インストールの方法が記載されていたので、以下のような手順で手動インストールしてみる事にする。

  1. DBFlute の配置
  2. DBFlute テンプレートの配置
  3. 設定ファイルの変更

なお、自動インストールの場合は Eclipse の Package Explorer(Navigator では駄目なので注意)でプロジェクトを選択し、「New」->「Other」、「DBFlute Wizards」->「DBFlute Client Directory」を実行すればよい。

DBFlute の配置

DBFlute のアーカイブファイルを適用先プロジェクトの任意のディレクトリ内に解凍する。(mydbflute への解凍が推奨されている模様)

(解凍先の例)
testprj/mydbflute/dbflute-0.5.6
DBFlute テンプレートの配置

解凍した dbflute ディレクトリ内 etc/client_directory_template ディレクトリに用意されている以下の 3つのテンプレートから 1つを選び、適用するプロジェクトの任意のディレクトリにコピーする。

  • fullProperties(上級者用、全ての Property の記述 #1)
  • minimumProperties(初心者用、最低限の Property の記述 #1)
  • otherORMapper

#1 ・・・ build-xxx.properties ファイルの設定項目数の違い

(配置先の例)
testprj/dbflute_testprj
設定ファイルの変更

コピーしたテンプレートディレクトリの _project.bat ファイルを以下のように編集。

  • MY_PROJECT_NAME の値を変更
  • DBFLUTE_HOME を有効化し値を設定
(_project.bat ファイル設定例)
set MY_PROJECT_NAME=testprj
set DBFLUTE_HOME=..\mydbflutedbflute-0.5.6

build-minimumProperties.properties ファイル名を build-プロジェクト名.properties に変更し、@FirstProperty の記述がある箇所を環境に合わせて編集。

(build-testprj.properties ファイル設定例)
torque.project = testprj
torque.database = h2
torque.packageBase = aaa.dbflute

DB の設定に合わせて dfprop/databaseInfoMap.dfprop ファイルを編集

(H2 用の設定例)
map:{
  ; driver        = org.h2.Driver
  ; url           = jdbc:h2:tcp://localhost:9092/demo
  ; schema        = 
  ; user          = sa
  ; password      =
}

ソースの自動生成と環境設定

次に、DB スキーマからソースコードを自動生成し、プロジェクトで DBFlute を使用する設定を実施する。
今回はプロジェクトの作成時に自動的に用意される H2 の DEPT テーブルと EMP テーブルをそのまま使うことにした。

ソースの自動生成

jdbc.bat ファイルを実行する(schema/project-schema-[project].xml ファイルが生成されていれば成功)

>jdbc.bat

generate.bat ファイルを実行する(torque.packageBase で指定したパッケージにソースファイルが生成されていれば成功)

>generate.bat
app.dicon の変更

DBFlute を使用できるように、プロジェクトの src/main/resources/app.dicon ファイルを以下のように変更する。(dao.dicon の代わりに dbflute.dicon を include)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
 "http://www.seasar.org/dtd/components24.dtd">
<components>
    <include path="convention.dicon"/>
    <include path="aop.dicon"/>
    <include path="app_aop.dicon"/>
    <include path="teedaExtension.dicon"/>
    <!-- dao.dicon の代わりに dbflut.dicn を include するように変更
    <include path="dao.dicon"/>
    -->
    <include path="dbflute.dicon"/>
    <include path="dxo.dicon"/>
</components>

DEPT 一覧表示ページの作成

DEPT テーブルの内容を一覧表示する HTML とページクラスを作成。

src/main/webapp/view/list.html
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<form id="Form">
<table>
<div id="dataItems">
    <tr>
        <td><span id="deptNo">1</span></td>
        <td><span id="deptName">名称</span></td>
        <td><span id="loc">場所</span></td>
    </tr>
</div>
</table>
<a id="goAddDept" href="addDept.html">Add dept</a>
</form>
</body>
</html>

DEPT の内容を一覧表示し、Add dept で新規登録ページに移動するようにしている。

src/main/java/aaa/web/ListPage.java
package aaa.web;

import java.math.BigDecimal;
import java.util.List;

import org.seasar.teeda.extension.annotation.scope.PageScope;

import aaa.dbflute.cbean.DeptCB;
import aaa.dbflute.exbhv.DeptBhv;
import aaa.dbflute.exentity.Dept;

public class ListPage {
    public int dataIndex;
    public List<Dept> dataItems;
    @PageScope public BigDecimal deptNo;
    @PageScope public String deptName;
    @PageScope public String loc;

    public DeptBhv deptBhv;

    public Class initialize() {
        return null;
    }

    public Class prerender() {
        this.dataItems = this.deptBhv.selectList(new DeptCB());
        return null;
    }
}

DeptBhv は DBFlute によって自動生成されたクラスで自動的に DI される。
なお、このサンプルでは DTO クラスを使わずにエンティティクラスを直接使う事にした。

DEPT 新規登録ページの作成

DEPT テーブルにレコードを新規登録するための HTML とページクラスを作成。

src/main/webapp/view/addDept.html
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<form id="Form">
<h1>Dept の登録</h1>
No: <input id="deptNo" type="text" /><br />
名称: <input id="deptName" type="text" /><br />
場所: <input id="loc" type="text" /><br />
<span id="allMessages" />
<input id="doAdd" type="submit" value="新規登録" />
</form>
</body>
</html>
src/main/java/aaa/web/AddDeptPage.java
package aaa.web;

import java.math.BigDecimal;

import org.seasar.teeda.extension.annotation.scope.PageScope;

import aaa.dbflute.exbhv.DeptBhv;
import aaa.dbflute.exentity.Dept;

public class AddDeptPage {

    @PageScope public BigDecimal deptNo;
    @PageScope public String deptName;
    @PageScope public String loc;

    public DeptBhv deptBhv;
    
    public Class doAdd() {
        Dept dept = new Dept();
        dept.setId(new BigDecimal(this.deptBhv.getCountAll() + 1));
        dept.setDeptNo(this.deptNo);
        dept.setDeptName(this.deptName);
        dept.setLoc(this.loc);

        this.deptBhv.insert(dept);

        return ListPage.class;
    }

    public Class initialize() {
        return null;
    }

    public Class prerender() {
        return null;
    }
}

新規登録後に一覧ページに遷移するように実装。

DEPT 新規登録ページで S2Dxo を使用

AddDeptPage クラスの doAdd メソッド内の処理を S2Dxo を使うように変更する。

S2Dxo では、インターフェースに変換元と変換先を指定した以下のような convert メソッドを定義するだけで、プロパティの自動マッピングが可能となる。

  • 変換先型 convert(変換元型)
  • void convert(変換元型, 変換先型)

なお、変換元と変換先でプロパティ名が異なる場合は、@ConversionRule アノテーションを使用する。

  • @ConversionRule("変換元プロパティ名 : 変換先プロパティ名,・・・")

AddDeptPage クラスのプロパティを Dept クラスのプロパティにマッピングするメソッドを定義した S2Dxo のインターフェースを定義し、DeptDxo を使用するように AddDeptPage クラスを変更する。

src/main/java/aaa/web/DeptDxo.java
package aaa.web;

import aaa.dbflute.exentity.Dept;

public interface DeptDxo {
    Dept convert(AddDeptPage page);
}
src/main/java/aaa/web/AddDeptPage.java
・・・
public class AddDeptPage {
    ・・・
    public DeptBhv deptBhv;
    public DeptDxo deptDxo;

    public Class doAdd() {
        Dept dept = this.deptDxo.convert(this);
        dept.setId(new BigDecimal(this.deptBhv.getCountAll() + 1));

        this.deptBhv.insert(dept);

        return ListPage.class;
    }
・・・