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>

注意 associationresultMap 中加上了命名空间, 不然是找不到的.

进阶二: 复用 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 和列都可以复用了.

进阶三

还没有想到, 有什么好想法, 欢迎留言.

posted @ 2019-04-04 16:19  hsnotebook  阅读(8022)  评论(0编辑  收藏  举报