MyBatis | Mapping Query Results to Arbitrary Java Objects | Mapping to Different Classes Based on Conditions
This method is mainly used when mapping classes that have an inheritance relationship.
DB table
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 |
Source code
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>
Execution result of selectBase
Hoge [value=hoge1, id=1, commonValue=common1]
Fuga [value=fuga2, id=2, commonValue=common2]
Base [id=3, commonValue=common3]
Explanation
- By using the <discriminator> tag, you can map to different classes depending on a condition.
- Specify the column that contains the condition value in the column attribute.
- The <case> tag defines which mapping is performed for each condition value.
- In this example, value 1 maps to the Hoge class and value 2 maps to the Fuga class.
- If the condition value does not exist in a <case> expression, it is mapped to the type specified in the original <resultMap> tag.
Defining mappings externally for each case
Source code
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>
Execution result
Hoge [value=hoge1, id=1, commonValue=null]
Fuga [value=fuga2, id=2, commonValue=common2]
Base [id=3, commonValue=common3]
Explanation
- The definition for each <case> can be extracted into a <resultMap>.
- However, in that case, columns defined in the common part are not mapped except for <id>, so they must be defined in each individual <resultMap>.
- hogeResultMap does not define commonValue, so it is null.
- If redefining common items in each individual <resultMap> is tedious, MyBatis provides the extends attribute.
Inheriting common parts with the extends attribute
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>
<!-- Inherit baseResultMap with extends. -->
<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>
Execution result
Hoge [value=hoge1, id=1, commonValue=common1]
Fuga [value=fuga2, id=2, commonValue=common2]
Base [id=3, commonValue=common3]