官方文檔: 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
和列都可以復用了.
進階三
還沒有想到, 有什么好想法, 歡迎留言.