<resultMap>是Maybatis的结果集封装,搭配<select><association>等标签的resultMap属性使用
属性:
id:该封装规则的唯一标识
type:封装出来的类型,可以是jdk自带的,比如Map,应该可以是自定义的,比如Employee
autoMapping:自动封装,如果数据库字段和javaBean的字段名一样,可以使用这种方式,但是不建议采取,还是老老实实写比较稳妥,如果非要使用此功能,那就在全局配置中加上mapUnderscoreToCamelCase=TRUE,它会使经典数据库字段命名规则翻译成javaBean的经典命名规则,如:a_column翻译成aColumn
extends:继承其他封装规则,和Java中的继承一样,也特别适合这样的场景
子标签:
<id>
用来标识出对象的唯一性,比如用表的主键,如:
<id column="employee_id" property="empId"/>
column指定数据库字段名或者其别名
property指定javaBean的属性名
还有jdbcType,javaType,typeHandler,分别数据库类型,属性的java类型,数据库与Java类型匹配处理器
默认的类型匹配处理器有:
145012_VWtp_3049601.png
以上罗列的资料不全,可以参考官方文档的如下章节
145150_qXkB_3049601.png
<result>
非主键的映射规则
<result column="dept_name" property="deptName"/>
<association>
属性:
property:同<id>标签
javaType:同<id>标签
select:指定嵌套SQL,可以是本XML或者其他XML文件中的<select>
fetchType:延迟加载,lazy打开延迟加载;eager积极加载
column:同<id>标签
resultMap:不使用嵌套SQL,而是使用复杂SQL一次取出关联的对象,并封装,对应下面的方式三
resultSet:引用根据<select>标签得到的resultSets,如:
SELECT * FROM BLOG WHERE ID = #{id}
SELECT * FROM AUTHOR WHERE ID = #{id}
<select id="selectBlog" resultSets="blogs,authors" resultMap="blogResult" statementType="CALLABLE">
{call getBlogsAndAuthors(#{id,jdbcType=INTEGER,mode=IN})}
</select>
<resultMap id="blogResult" type="Blog">
<id property="id" column="id" />
<result property="title" column="title"/>
<association property="author" javaType="Author" resultSet="authors" column="author_id" foreignColumn="id">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="email" column="email"/>
<result property="bio" column="bio"/>
</association>
</resultMap>
autoMapping:同<id>标签
columnPrefix:关联多张表查询时,为了使列明不重复,使用此功能可以减少开发量
<select id="selectBlog" resultMap="blogResult">
select
B.id as blog_id,
B.title as blog_title,
A.id as author_id,
A.username as author_username,
A.password as author_password,
A.email as author_email,
A.bio as author_bio,
CA.id as co_author_id,
CA.username as co_author_username,
CA.password as co_author_password,
CA.email as co_author_email,
CA.bio as co_author_bio
from Blog B
left outer join Author A on B.author_id = A.id
left outer join Author CA on B.co_author_id = CA.id
where B.id = #{id}
</select>
抽取出共同的resultMap,因为作者和其他作者都具有同样的属性,因此有:
<resultMap id="authorResult" type="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
<result property="password" column="author_password"/>
<result property="email" column="author_email"/>
<result property="bio" column="author_bio"/>
</resultMap>
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<association property="author"
resultMap="authorResult" />
<association property="coAuthor"
resultMap="authorResult"
columnPrefix="co_" />
</resultMap>
foreignColumn:外键列
notNullColumn:不为空的列,如果指定了列,那么只有当字段不为空时,Mybatis才会真正创建对象,才能得到我们想要的值
typeHandler:同<id>标签
方式一:
<!-- 嵌套方式 -->
<resultMap type="com.jv.bean.Employee" id="EmpAndDeptMethod2">
<id column="employee_id" property="employeeId"/>
<result column="first_name" property="firstName"/>
<result column="last_name" property="lastName"/>
<result column="gendor" property="gendor"/>
<result column="birthday" property="birthday"/>
<!-- 可以将下面这部分抽离出来单独使用一个resultMap进行标记,然后在association标签中使用resultMap指向该标记 -->
<association property="dept" javaType="com.jv.bean.DepartMent">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
<result column="dept_desc" property="deptDesc"/>
</association>
</resultMap>
<select id="getEmployeeDetailInfo2" resultMap="EmpAndDeptMethod2">
select employee_id,first_name,last_name,gendor,birthday,a.dept_id,dept_name,dept_desc
from employee a,department b
where a.dept_id=b.dept_id
and a.employee_id=#{id}
</select>
方式二:
<!-- 分布查询 -->
<!--
该功能有一个很重要的用途:可以支持延迟加载(按需加载),需要在全局配置文件中增加:
lazyLoadingEnabled 打开延迟加载
aggressiveLazyLoading 设置为TRUE是使用时全部加载,false是按需加载
这两个配置。
-->
<resultMap type="com.jv.bean.Employee" id="EmpAndDeptMethod3">
<id column="employee_id" property="employeeId"/>
<result column="first_name" property="firstName"/>
<result column="last_name" property="lastName"/>
<result column="gendor" property="gendor"/>
<result column="birthday" property="birthday"/>
<association property="dept"
select="com.jv.dao.DepartMentMapper.getDepartMentByIdNew" column="dept_id">
</association>
<association property="post"
select="com.jv.dao.PostMapper.getPostById" column="post_id">
</association>
</resultMap>
<select id="getEmployeeDetailInfo3" resultMap="EmpAndDeptMethod3">
select employee_id,first_name,last_name,gendor,birthday,dept_id,post_id
from employee a
where a.employee_id=#{id}
</select>
方式三:
<!-- 嵌套方式 -->
<resultMap type="com.jv.bean.Employee" id="EmpAndDeptMethod2">
<id column="employee_id" property="employeeId"/>
<result column="first_name" property="firstName"/>
<result column="last_name" property="lastName"/>
<result column="gendor" property="gendor"/>
<result column="birthday" property="birthday"/>
<!-- 可以将下面这部分抽离出来单独使用一个resultMap进行标记,然后在association标签中使用resultMap指向该标记 -->
<association property="dept" resultMap="deptMap">
</association>
</resultMap>
<resultMap id="deptMap" javaType="com.jv.bean.DepartMent">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
<result column="dept_desc" property="deptDesc"/>
</resultMap>
<select id="getEmployeeDetailInfo2" resultMap="EmpAndDeptMethod2">
select employee_id,first_name,last_name,gendor,birthday,a.dept_id,dept_name,dept_desc
from employee a,department b
where a.dept_id=b.dept_id
and a.employee_id=#{id}
</select>
<collection>
和association很像,collection是负责处理多行的结果集,如:
方式一:
使用嵌套SQL
<resultMap id="blogResult" type="Blog">
<collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>
</resultMap>
<select id="selectBlog" resultMap="blogResult">
SELECT * FROM BLOG WHERE ID = #{id}
</select>
<select id="selectPostsForBlog" resultType="Post">
SELECT * FROM POST WHERE BLOG_ID = #{id}
</select>
方式二:
使用复杂查询-在collection中直接配置封装规则
<select id="selectBlog" resultMap="blogResult">
select
B.id as blog_id,
B.title as blog_title,
B.author_id as blog_author_id,
P.id as post_id,
P.subject as post_subject,
P.body as post_body,
from Blog B
left outer join Post P on B.id = P.blog_id
where B.id = #{id}
</select>
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
</collection>
</resultMap>
方式三:
使用复杂查询-抽取封装规则放到resultMap中
<select id="selectBlog" resultMap="blogResult">
select
B.id as blog_id,
B.title as blog_title,
B.author_id as blog_author_id,
P.id as post_id,
P.subject as post_subject,
P.body as post_body,
from Blog B
left outer join Post P on B.id = P.blog_id
where B.id = #{id}
</select>
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<collection property="posts" ofType="Post" resultMap="blogPostResult" columnPrefix="post_"/>
</resultMap>
<resultMap id="blogPostResult" type="Post">
<id property="id" column="id"/>
<result property="subject" column="subject"/>
<result property="body" column="body"/>
</resultMap>
方式二和方式三只有在封装的方式上有区别
<descriminator>
负责根据返回的字段的值封装不同的类型,如:
<resultMap id="vehicleResult" type="Vehicle">
<id property="id" column="id" />
<result property="vin" column="vin"/>
<result property="year" column="year"/>
<result property="make" column="make"/>
<result property="model" column="model"/>
<result property="color" column="color"/>
<discriminator javaType="int" column="vehicle_type">
<case value="1" resultMap="carResult"/>
<case value="2" resultMap="truckResult"/>
<case value="3" resultMap="vanResult"/>
<case value="4" resultMap="suvResult"/>
</discriminator>
</resultMap>
<resultMap id="carResult" type="Car" extends="vehicleResult">
<result property="doorCount" column="door_count" />
</resultMap>
上面的配置就是如果vehicle_type的值是1,那么封装的结果为carResult,同事carResult又继承了vehicleResult的所有普通封装规则,最后的它结果可以按照下面的配置理解
<resultMap id="carResult" type="Vehicle">
<id property="id" column="id" />
<result property="vin" column="vin"/>
<result property="year" column="year"/>
<result property="make" column="make"/>
<result property="model" column="model"/>
<result property="color" column="color"/>
<result property="doorCount" column="door_count"/>
</resultMap>
<constructor>
使用构造器注入属性值,可能会问既然通过<id>和<result>就可以给属性注入值了,为什么还有一个构造器注入的,原因是有的JavaBean没有提供属性的getter和setter方法。
<constructor>
<idArg column="id" javaType="int" name="id" />
<arg column="age" javaType="_int" name="age" />
<arg column="username" javaType="String" name="username" />
</constructor>
为了维护更方便,推荐在使用构造器注入的时候加上name属性,该属性值与构造器参数名字相同(需要编译参数加上-parameters,Jdk版本为1.8,而且Mybatis的参数useActualParamName设置为true(默认值为true)),也可以使用@param("paramName")指定特殊的参数名。
转载于:https://my.oschina.net/u/3049601/blog/1613921
mybatis resultMap映射详解
最新推荐文章于 2023-03-25 16:39:06 发布