Kuina-Dao を使ってみる

id:fits:20070617 では、S2Hibernate-JPA の簡単なサンプルを作ってみたが、これを EntityManager の使用を隠蔽し簡単に JPA を使用するためのフレームワーク Kuina-Dao を使うように変更してみる。

手順は以下の通り。

  1. Kuina-Dao の JAR ファイルをクラスパスに追加
  2. dicon ファイルの追加と編集
  3. Dao 実装の削除とサービスの作成
  4. テストクラスの変更

実際のところ、Eclipse プラグインの Dolteng を使えば簡単に環境を作成してくれて便利なのだが、Dolteng だと設定内容や仕組みが分かり難かったため、自分で環境を構築してみる事にした。

Kuina-Dao の JAR ファイルをクラスパスに追加

kuina-dao\lib\kuina-doa-1.0.0.jar ファイルをクラスパスに追加する

dicon ファイルの追加と編集

SMART Deploy の Deploy 方式を設定する s2container.dicon ファイルを追加
<components>
    <include path="hotdeploy.dicon"/>
</components>

SMART deploy 機能の Deploy 形式に応じた dicon を include する。

どれか 1つの dicon を include するようにしないと、実行時にコンポーネントが見つからないなどのエラーが発生するので注意。

customizer.dicon の編集

daoCustomizer を有効化し、kuinaDaoCustomizer を指定する。

<components>
    <include path="default-customizer.dicon"/>
    <component name="daoCustomizer" class="org.seasar.framework.container.customizer.CustomizerChain">
        <initMethod name="addCustomizer">
            <arg>traceCustomizer</arg>
        </initMethod>
        <initMethod name="addCustomizer">
            <arg>kuinaDaoCustomizer</arg>
        </initMethod>
    </component>
</components>
app.dicon の編集

S2Hibernate-JPA 用に記述した app.dicon を全面的に変更する。
customizer.dicon で kuinaDaoCustomizer を指定した場合、kuina-dao.dicon の include は必須。

<components>
    <include path="convention.dicon"/>
    <include path="aop.dicon"/>
    <include path="kuina-dao.dicon"/>
    <include path="dxo.dicon"/>
</components>

Dao 実装の削除とサービスの作成

Dao 実装の削除、Dao インターフェースの変更

Kuina-Dao では、Dao の実装クラスは AOP によって提供されるため、Dao インターフェースを用意するだけで良いので、S2Hibernate-JPA の時に用意したような Dao の実装クラスは不要。

なお、Kuina-Dao ではこの Dao インターフェースで EntityMangaer の使用を隠蔽する。

package aaa.dao;

import java.util.List;

import aaa.entity.*;

public interface DeptDao {

    Dept find(long id);
    void persist(Dept dept);
}
サービスインターフェースの作成

アプリケーションの機能を定義するためのサービスインターフェースを作成

package aaa.service;

import aaa.entity.*;

public interface SampleService {
    long add(String name);
    Dept find(long id);
}
サービスインターフェースの実装クラス作成

S2Hibernate-JPA のサンプルでは Dao の実装クラスで行っていたものと同様の処理をサービスインターフェースの実装クラスで実装する。

Dao の実装クラスを DI させる部分に @EJB アノテーションを使用。

package aaa.service.impl;

import javax.ejb.*;

import aaa.dao.*;
import aaa.entity.*;
import aaa.service.*;

@Stateless
public class SampleServiceImpl implements SampleService {

    @EJB
    private DeptDao dao;

    public long add(String name) {
        Dept dept = new Dept();
        dept.setDeptName(name);

        dao.persist(dept);
        return dept.getId();
    }

    public Dept find(long id) {
        return dao.find(id);
    }
}

テストクラスの変更

サービスのインターフェースを指定してコンポーネントを取得

package test;

import javax.persistence.*;

import org.seasar.framework.container.*;
import org.seasar.framework.container.factory.*;

import aaa.dao.*;
import aaa.entity.*;

public class Test {
    public static void main(String[] args) {
        SingletonS2ContainerFactory.init();

        SampleService service = SingletonS2Container.getComponent(SampleService.class);

        long id = service.add("テストデータ");
        System.out.println(id);

        Dept dept = service.find(id);
        System.out.println(dept.getDeptName());
    }
}

ちなみに、ビルドやテストクラスの実行に以下のような Ant 用ビルドファイルを使用した。

<?xml version="1.0" encoding="UTF-8" ?>
<project name="" default="compile" basedir=".">
    <property environment="env" />

    <property name="src.dir" value="src" />
    <property name="conf.dir" value="conf" />
    <property name="dest.dir" value="dest" />

    <path id="project.classpath">
        <pathelement path="${dest.dir}" />
        <fileset dir="${env.KUINADAO_HOME}/lib">
            <include name="**/*.jar" />
        </fileset>
        <fileset dir="${env.S2CONTAINER_HOME}/lib">
            <include name="**/*.jar" />
        </fileset>
        <fileset dir="${env.S2TIGER_HOME}/lib">
            <include name="**/*.jar" />
        </fileset>
        <fileset dir="${env.S2HIBERNATE_JPA_HOME}/lib">
            <include name="**/*.jar" />
        </fileset>
    </path>

    <target name="compile">
        <mkdir dir="${dest.dir}" />
        <copy todir="${dest.dir}">
            <fileset dir="${conf.dir}" />
        </copy>

        <javac srcdir="${src.dir}" destdir="${dest.dir}">
            <classpath refid="project.classpath" />
            <include name="**/*.java" />
        </javac>

    </target>

    <target name="run" depends="compile">
        <java classname="test.Test" fork="yes">
            <classpath refid="project.classpath" />
        </java>
    </target>

    <target name="clean">
        <delete dir="${dest.dir}" />
    </target>
</project>