MyBatis | 検索結果を任意のJavaオブジェクトにマッピング | 条件に応じて別のクラスにマッピングする

主に継承関係にあるクラスをマッピングするときに使用する方法である。

DBテーブル

base_table

id common_value type hoge_value fuga_value piyo_value
1 common1 1 hoge1 fuga1 piyo1
2 common2 2 hoge2 fuga2 piyo2
3 common3 3 hoge3 fuga3 piyo3

ソースコード

Base.java

package sample.mybatis;

public class Base {
    protected int id;
    protected String commonValue;

    @Override
    public String toString() {
        return "Base [id=" + id + ", commonValue=" + commonValue + "]";
    }
}

Hoge.java

package sample.mybatis;

public class Hoge extends Base {
    private String value;

    @Override
    public String toString() {
        return "Hoge [value=" + value + ", id=" + id + ", commonValue=" + commonValue + "]";
    }
}

Fuga.java

package sample.mybatis;

public class Fuga extends Base {
    private String value;

    @Override
    public String toString() {
        return "Fuga [value=" + value + ", id=" + id + ", commonValue=" + commonValue + "]";
    }
}

sample_mapper.xml

<?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="sample.mybatis">

  <resultMap type="sample.mybatis.Base" id="baseResultMap">
    <id property="id" column="id" />
    <result property="commonValue" column="common_value" />

    <discriminator javaType="int" column="type">
      <case value="1" resultType="sample.mybatis.Hoge">
        <result property="value" column="hoge_value" />
      </case>
      <case value="2" resultType="sample.mybatis.Fuga">
        <result property="value" column="fuga_value" />
      </case>
    </discriminator>
  </resultMap>

  <select id="selectBase" resultMap="baseResultMap">
    select * from base_table
  </select>
</mapper>

selectBaseの実行結果

Hoge [value=hoge1, id=1, commonValue=common1]
Fuga [value=fuga2, id=2, commonValue=common2]
Base [id=3, commonValue=common3]

説明

  • <discriminator>タグを使用することで、条件に応じて別のクラスにマッピングできる。
    • column属性には条件値を持つカラムを指定する。
  • <case>タグで、条件値に対してどのマッピングを行うかを定義する。
    • ここでは1の場合はHogeクラス、2の場合はFugaクラスにマッピングするよう定義している。
  • <case>式に存在しない条件値の場合は、元の<resultMap>タグで指定したtypeにマッピングされる。

ケースごとにマッピングを外部設定にする

ソースコード

sample_mapper.xml

<?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="sample.mybatis">

  <resultMap type="sample.mybatis.Base" id="baseResultMap">
    <id property="id" column="id" />
    <result property="commonValue" column="common_value" />

    <discriminator javaType="int" column="type">
      <case value="1" resultMap="hogeResultMap" />
      <case value="2" resultMap="fugaResultMap" />
    </discriminator>
  </resultMap>

  <resultMap type="sample.mybatis.Hoge" id="hogeResultMap">
    <result property="value" column="hoge_value" />
  </resultMap>

  <resultMap type="sample.mybatis.Fuga" id="fugaResultMap">
    <result property="value" column="fuga_value" />
    <result property="commonValue" column="common_value" />
  </resultMap>

  <select id="selectBase" resultMap="baseResultMap">
    select * from base_table
  </select>
</mapper>

実行結果

Hoge [value=hoge1, id=1, commonValue=null]
Fuga [value=fuga2, id=2, commonValue=common2]
Base [id=3, commonValue=common3]

説明

  • <case>ごとの定義は<resultMap>に切り出せる。
  • ただし、その場合は共通部分として定義したカラムは<id>以外マッピングされないため、個別の<resultMap>で定義しなければならない。
    • hogeResultMapはcommonValueを定義していないためnullになっている。
  • 個別の<resultMap>で共通項目を毎回定義し直すのが大変な場合は、extends属性を使用する方法が用意されている。

extends属性で共通部分を継承する

sample_mapper.xml

<?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="sample.mybatis">

  <resultMap type="sample.mybatis.Base" id="baseResultMap">
    <id property="id" column="id" />
    <result property="commonValue" column="common_value" />

    <discriminator javaType="int" column="type">
      <case value="1" resultMap="hogeResultMap" />
      <case value="2" resultMap="fugaResultMap" />
    </discriminator>
  </resultMap>
                                                           <!-- extendsでbaseResultMapを継承 -->
  <resultMap type="sample.mybatis.Hoge" id="hogeResultMap" extends="baseResultMap">
    <result property="value" column="hoge_value" />
  </resultMap>

  <resultMap type="sample.mybatis.Fuga" id="fugaResultMap" extends="baseResultMap">
    <result property="value" column="fuga_value" />
  </resultMap>

  <select id="selectBase" resultMap="baseResultMap">
    select * from base_table
  </select>
</mapper>

実行結果

Hoge [value=hoge1, id=1, commonValue=common1]
Fuga [value=fuga2, id=2, commonValue=common2]
Base [id=3, commonValue=common3]