官方文档:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#Auto-mapping
- 在一般的场景下,MyBatis可以替我们自动映射查询结果。如映射到Java Bean中,MyBatis会获取sql返回的列名并在java类中查找相同名字的属性(忽略大小写)。
- 在复杂的场景下,通常构建一个result map(<resultMap>)。自动映射在特定的<resultMap>下也能工作,对于每一个result map,所有的ResultSet提供的列, 如果没有被手工映射,则将被自动映射。自动映射处理完毕后手工映射才会被处理。
1. 与自动映射相关的配置
(1)<setting name="autoMappingBehavior" vlaue="NONE | PARTIAL | FULL"/>
指定 MyBatis 应如何自动映射列到字段或属性。
- NONE:表示取消自动映射
- PARTIAL:只会自动映射没有定义嵌套结果集映射的结果集
- FULL:会自动映射任意复杂的结果集(无论是否嵌套)
(2)<resultMap>标签的automapping属性
2. <ResultMap>标签的自动映射
2.1 不启用自动映射
有两种情况:
- autoMappingBehavior=NONE,autoMapping不指定
- autoMappingBehavior=PARTIAL或FULL,autoMapping=false
不启用自动映射时,MyBatis只会根据<resultMap>元素里手动定义的属性查询的列进行映射。
示例:
配置autoMappingBehavior=PARTIAL或FULL,autoMapping=false;User类里有id,userName,userGender,age等属性,查询出所有的列;<resultMap>里只配置id、userName的映射。
- 此时查询用户,User中只有id、userName有数据
- 若将autoMapping属性去掉或设置为true,此时即可获取到age属性的值;userGender仍获取不到
(1)mybatis配置文件
<settings>
<!-- 指定 MyBatis 应如何自动映射列到字段或属性,默认值:PARTIAL -->
<setting name="autoMappingBehavior" value="PARTIAL"/>
......
</settings>
(2)UserMapper.xml
<resultMap type="User" id="userMap" autoMapping="false">
<id property="id" column="id"/>
<result property="userName" column="user_name"/>
</resultMap>
<sql id="Base_Column_List">
id, user_name, user_gender, age
</sql>
<select id="findUserById" parameterType="int" resultMap="userMap">
select
<include refid="Base_Column_List"/>
from t_user_automapping
where id = #{id}
</select>
2.2 启动自动映射
有三种情况:
- autoMappingBehavior=NONE,autoMapping="true"
- autoMappingBehavior=PARTIAL,autoMapping="true"或不指定
- autoMappingBehavior=FULL,autoMapping="true"或不指定
第一、二种配置自动映射情况相同,会先自动映射与列名相同的JavaBean属性,然后再映射手动配置的属性。不处理嵌套结果的映射,如<assocation>、<collection>标签里的嵌套映射。
第三种配置在第一、二种自动映射的基础上,还可以对嵌套结果的映射。
示例一(第二种配置):
此时User类的id,user_name,age属性可以获取到数据,userGender获取不到;因为查询出的列是user_gender,MyBatis无法进行自动映射。(可行的解决方法在文章最后列出,这里先跳过)
(1)mybatis配置文件
<settings>
<!-- 指定 MyBatis 应如何自动映射列到字段或属性,默认值:PARTIAL -->
<setting name="autoMappingBehavior" value="PARTIAL"/>
......
</settings>
(2)UserMapper.xml
<resultMap type="User" id="userMap">
<id property="id" column="id"/>
<result property="userName" column="user_name"/>
</resultMap>
<sql id="Base_Column_List">
id, user_name, user_gender, age
</sql>
<select id="findUserById" parameterType="int" resultMap="userMap">
select
<include refid="Base_Column_List"/>
from t_user_automapping
where id = #{id}
</select>
示例二(第三种配置):
此时User类的id,user_name,age属性可以获取到数据,userGender获取不到;
User类关联了Card,id通过手动映射,code通过自动映射,也可以获取到相应的值(因为配置了autoMappingBehavior=FULL)
(1)mybatis配置文件
<settings>
<!-- 指定 MyBatis 应如何自动映射列到字段或属性,默认值:PARTIAL -->
<setting name="autoMappingBehavior" value="FULL"/>
......
</settings>
(2)UserMapper.xml
<resultMap type="User" id="userMap">
<id property="id" column="id"/>
<result property="userName" column="user_name"/>
<!-- 关联Card -->
<association property="card" javaType="Card" column="card_id" columnPrefix="c_">
<id property="id" column="id"/>
</association>
</resultMap>
<sql id="Base_Column_List">
id, user_name, user_gender, age
</sql>
<select id="findUserById" parameterType="int" resultMap="userMap">
select
t.id,
t.user_name,
t.user_gender,
t.user_age,
t.card_id,
c.id as c_id,
c.code as c_code
from t_user t left join t_card c on t.card_id = c.id
where t.id = #{id}
</select>
注意:
- 若 <association>不配置columnPrefix="c_"属性,同时sql对于c.id as c_id也不设置别名,那么就会导致t_user表的id映射到Card的id属性。所以需通过columnPrefix="c_"只设置带有"c_"前缀的列与Card属性进行映射。
- 配置了columnPrefix="c_"属性:自动、手动映射都有效,若c.code as c_code修改为c.code,则无法获取Card#code属性值
3. 处理user_gender与userGender的自动映射
(1)最简单的方式是给user_gender起别名,即select user_gender as userGender,此时与User类里的userGender属性一致
(2)在MyBatis配置文件里添加mapUnderscoreToCamelCase=true配置,表示开启自动驼峰命名规则,自动将user_gender与Java属性名userGender进行映射
<settings>
<!-- 指定 MyBatis 应如何自动映射列到字段或属性,默认值:PARTIAL -->
<setting name="autoMappingBehavior" value="PARTIAL"/>
<!-- 开启自动驼峰命名规则(camel case)映射,默认值:false。
即从经典数据库列名user_gender到Java属性名userGender的类似映射
-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
...
</settings>
对关联映射、集合映射不太了解的可以查阅下官方文档,以及我整理的两篇博客: