似非プログラマのうんちく

「似非プログラマの覚え書き」出張版

MyBatis + Guice でカンタン DAO 実装(その 1)

O/R マッパーである MyBatis と軽量 DI コンテナ Guice による DAO 実装について、今回から数回に分けて書きます。

MyBatis とは

MyBatis は iBatis の後継となる O/R マッパー。マッピングファイルに SQL を記述し、インターフェースを用意することで、マッピングファイルから自動的にインターフェースの実装をしてくれる。

Guice とは

Google が開発している Java 向けの軽量 DI コンテナ。DI は "Dependency Injection" の略で、日本語に訳すと「依存性の注入」。外部のオブジェクトに依存する部分を、実行時に外部から注入する仕組みで、オブジェクト間の依存関係をソースコードから排除し、オブジェクトの独立性を高め、単体テストをしやすくする。

下準備

今回使用するテーブルについて

データベースは MySQL を使用。

必要なライブラリ

  • MyBatis
    • mybatis-3.2.5.jar
  • Guice*1
    • guice-3.0.jar
    • javax.inject.jar
    • aopalliance.jar
  • MyBatis + Guice 連携
  • Velocity*2
    • velocity-1.7.jar
    • velocity-tools-2.0.jar
    • commons-beanutils-1.9.1.jar
    • commons-collections-3.2.1.jar
    • commons-digester-1.8.1.jar
    • commons-lang-2.6.jar
    • commons-logging-1.1.3.jar
  • JDBC ドライバ

DAO 層の実装

MyBatis の設定ファイル

まずは MyBatis の設定を mybatis-config.xml に記述する。ファイルはクラスパスの直下におくこと(Eclipse の動的 Web プロジェクトであれば、src フォルダの直下に置く)。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE configuration PUBLIC
  "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <typeAliases>
    <typeAlias
      type="jp.mydns.akanekodou.model.City"
      alias="City" />
  </typeAliases>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC" />
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/dbname" />
        <property name="username" value="username" />
        <property name="password" value="password" />
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="jp/mydns/akanekodou/dao/mapper/city-mapper.xml" />
  </mappers>
</configuration>

これは MySQL を使う場合の設定。dbname, username, password は適宜書き換える。他の RDBMS を使う場合は JDBC ドライバの部分や接続 URL も変わってくるので、その部分も適宜書き換える。

Java Beans の記述

モデルとなる Java Beans の記述。

package jp.mydns.akanekodou.bean;

import java.util.Date;

public class City {
    private int id;
    private String name;
    private String pref;
    private Date designatedDay;
    private double area;
    private int population;
    private String dstName;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPref() {
        return pref;
    }

    public void setPref(String pref) {
        this.pref = pref;
    }

    public Date getDesignatedDay() {
        return designatedDay;
    }

    public void setDesignatedDay(Date designatedDay) {
        this.designatedDay = designatedDay;
    }

    public double getArea() {
        return area;
    }

    public void setArea(double area) {
        this.area = area;
    }

    public int getPopulation() {
        return population;
    }

    public void setPopulation(int population) {
        this.population = population;
    }

    public String getDstName() {
        return dstName;
    }

    public void setDstName(String dstName) {
        this.dstName = dstName;
    }
}

マッピングファイルの記述

マッピングファイルと、それによって実装されるインターフェースの記述。まずはインターフェースから。

package jp.mydns.akanekodou.dao.mapper;

import java.util.List;

import jp.mydns.akanekodou.bean.City;

public interface CityMapper {
    List<City> all();
    City find(int id);
}

次にインターフェースを実装するためのマッピングファイル。CityMapper.java と同じパッケージ内に配置する。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE mapper PUBLIC
  "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="jp.mydns.akanekodou.dao.mapper.CityMapper">
  <resultMap id="cityResultMap" type="City">
    <id property="id" column="city_id" />
    <result property="name" column="city_name" />
    <result property="pref" column="pref_name" />
    <result property="designatedDay" column="designated_day" />
    <result property="area" column="area" />
    <result property="population" column="population" />
    <result property="dstName" column="dst_name" />
  </resultMap>
  <select id="all" resultMap="cityResultMap">
    SELECT
      c.city_id as city_id,
      c.city_name as city_name,
      c.pref_name as pref_name,
      c.designated_day as designated_day,
      c.area as area,
      c.population as population,
      d.dst_name as dst_name
    FROM
      major_city c
      NATURAL JOIN district d
    ORDER BY
      city_id
  </select>
  <select id="find" parameterType="int" resultMap="cityResultMap">
    SELECT
      c.city_id as city_id,
      c.city_name as city_name,
      c.pref_name as pref_name,
      c.designated_day as designated_day,
      c.area as area,
      c.population as population,
      d.dst_name as dst_name
    FROM
      major_city c
      NATURAL JOIN district d
    WHERE
      city_id = #{id}
  </select>
</mapper>

次回、Guice を用いて DAO を実装する。

*1:ここに挙げたものは全て guice-3.0.zip に含まれている。

*2:ビューの作成で使用。