MyBatis 使用另一个 mapper 中的 resultMap 和 sql
官方文档: http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html
官方文档很有用, 一定要仔细看.
背景
在查询过程中,经常会遇到关联查询的情况.
实体类关系, 如下:
每个实体有自己的 mapper 文件.
目的
查询 Blog 时, 把 Author 也一块查出来.
Blog 不复用 Author 中的配置
AuthorMapper.xml :
<mapper namespace="org.hsnotebook.mapper.AuthorMapper">
<resultMap id="authorResultMap" type="org.hsnotebook.entity.Author">
<id property="id" column="id" />
<result property="name" column="name" />
</resultMap>
<select id="selectAuthor" resultMap="authorResultMap">
select
a.id,
a.name,
from
t_author a
</select>
</mapper>
BlogMapper.xml :
<mapper namespace="org.hsnotebook.mapper.BlogMapper">
<resultMap id="blogResultMap" type="org.hsnotebook.entity.Blog">
<id property="id" column="id" />
<result property="title" column="title" />
<association property="author" javaType="Author">
<id property="id" column="a_id" />
<result property="name" column="a_name" />
</association>
</resultMap>
<select id="selectBlog" resultMap="blogResultMap">
select
b.id,
b.title,
b.author_id,
a.id as a_id,
a.name as a_name,
from
t_blog b left join t_author a on a.id = b.author_id
</select>
</mapper>
问题
重复就是最大的问题, Author 加个字段, 这两个 mapper 都需要改.
这个例子比较简单, 改也好改, 但是:
- 如果 Author 字段非常多呢?
- 如果 Blog 还有个联合作者, 叫 CoAuthor 呢?
- 如果还有另的实体也要对 Author 进行关联查询呢?
那重复的就不是一次两次的了, 到时候您就改去吧.
进阶一: 复用 Author 的 resultMap
association
有两个属性:
resultMap
使用这个结果映射columnPrefix
columnPrefix
的官方说明:
当连接多个表时,你可能会不得不使用列别名来避免在 ResultSet 中产生重复的列名。指定 columnPrefix 列名前缀允许你将带有这些前缀的列映射到一个外部的结果映射中.
使用这两个属性, 我们就可以使用 AuthorMapper.xml 中的 resutlMap
了.
BlogMapper.xml 改成下面这样:
<mapper namespace="org.hsnotebook.mapper.BlogMapper">
<resultMap id="blogResultMap" type="org.hsnotebook.entity.Blog">
<id property="id" column="id" />
<result property="title" column="title" />
<association property="author" resultMap="org.hsnotebook.mapper.AuthorMapper.authorResultMap" columnPrefix="a_">
</association>
</resultMap>
<select id="selectBlog" resultMap="blogResultMap">
select
b.id,
b.title,
b.author_id,
a.id as a_id,
a.name as a_name,
from
t_blog b left join t_author a on a.id = b.author_id
</select>
</mapper>
注意 association
的 resultMap
中加上了命名空间, 不然是找不到的.
进阶二: 复用 Author 的 列
上面只是 resultMap
省了, 可是对应的列还是要一遍一遍地一遍一遍地一遍一遍地...写.
还好 MyBatis 中可定义 sql 片段, 还可以传变量. 将 Author 的列提取出一个 sql 片段,并定义适当的变量.
AuthorMapper.xml 改成如下:
<mapper namespace="org.hsnotebook.mapper.AuthorMapper">
<resultMap id="authorResultMap" type="org.hsnotebook.entity.Author">
<id property="id" column="id" />
<result property="name" column="name" />
</resultMap>
<sql id='authorColumns'>
${alias}.id as ${prefix}id,
${alias}.name as ${prefix}name
</sql>
<select id="selectAuthor" resultMap="authorResultMap">
select
<include refid="authorColumns">
<property name="alias" value="a" />
<property name="prefix" value=""/>
</include>
from
t_author a
</select>
</mapper>
BlogMapper.xml :
<mapper namespace="org.hsnotebook.mapper.BlogMapper">
<resultMap id="blogResultMap" type="org.hsnotebook.entity.Blog">
<id property="id" column="id" />
<result property="title" column="title" />
<association property="author" resultMap="org.hsnotebook.mapper.AuthorMapper.authorResultMap" columnPrefix="a_">
</association>
</resultMap>
<select id="selectBlog" resultMap="blogResultMap">
select
b.id,
b.title,
b.author_id,
<include refid="org.hsnotebook.mapper.AuthorMapper.authorColumns">
<property name="alias" value="a" />
<property name="prefix" value="a_"/>
</include>
from
t_blog b left join t_author a on a.id = b.author_id
</select>
</mapper>
哒哒! 这样 Author 的 resultMap
和列都可以复用了.
进阶三
还没有想到, 有什么好想法, 欢迎留言.