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]