<collection property="posts" ofType="domain.blog.Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
</collection>
集合元素和關聯(lián)元素幾乎是一樣的,它們相似的程度之高,以致于沒有必要再介紹集合元素的相似部分。 所以讓我們來關注它們的不同之處吧。
我們來繼續(xù)上面的示例,一個博客(Blog)只有一個作者(Author)。但一個博客有很多文章(Post)。 在博客類中,這可以用下面的寫法來表示:
private List<Post> posts;
要像上面這樣,映射嵌套結果集合到一個 List 中,可以使用集合元素。 和關聯(lián)元素一樣,我們可以使用嵌套 Select 查詢,或基于連接的嵌套結果映射集合。
首先,讓我們看看如何使用嵌套 Select 查詢來為博客加載文章。
<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>
你可能會立刻注意到幾個不同,但大部分都和我們上面學習過的關聯(lián)元素非常相似。 首先,你會注意到我們使用的是集合元素。 接下來你會注意到有一個新的 “?ofType?” 屬性。這個屬性非常重要,它用來將 ?JavaBean?(或字段)屬性的類型和集合存儲的類型區(qū)分開來。 所以你可以按照下面這樣來閱讀映射:
<collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>
讀作: “posts 是一個存儲 Post 的 ArrayList 集合”
在一般情況下,MyBatis 可以推斷 ?javaType ?屬性,因此并不需要填寫。所以很多時候你可以簡略成:
<collection property="posts" column="id" ofType="Post" select="selectPostsForBlog"/>
現(xiàn)在你可能已經(jīng)猜到了集合的嵌套結果映射是怎樣工作的——除了新增的 “?ofType?” 屬性,它和關聯(lián)的完全相同。
首先, 讓我們看看對應的 SQL 語句:
<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>
再提醒一次,要記得上面 id 元素的重要性,如果你不記得了,請閱讀關聯(lián)部分的相關部分。
如果你喜歡更詳略的、可重用的結果映射,你可以使用下面的等價形式:
<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>
像關聯(lián)元素那樣,我們可以通過執(zhí)行存儲過程實現(xiàn),它會執(zhí)行兩個查詢并返回兩個結果集,一個是博客的結果集,另一個是文章的結果集:
SELECT * FROM BLOG WHERE ID = #{id}
SELECT * FROM POST WHERE BLOG_ID = #{id}
在映射語句中,必須通過 ?resultSets ?屬性為每個結果集指定一個名字,多個名字使用逗號隔開。
<select id="selectBlog" resultSets="blogs,posts" resultMap="blogResult">
{call getBlogsAndPosts(#{id,jdbcType=INTEGER,mode=IN})}
</select>
我們指定 “posts” 集合將會使用存儲在 “posts” 結果集中的數(shù)據(jù)進行填充:
<resultMap id="blogResult" type="Blog">
<id property="id" column="id" />
<result property="title" column="title"/>
<collection property="posts" ofType="Post" resultSet="posts" column="id" foreignColumn="blog_id">
<id property="id" column="id"/>
<result property="subject" column="subject"/>
<result property="body" column="body"/>
</collection>
</resultMap>
對關聯(lián)或集合的映射,并沒有深度、廣度或組合上的要求。但在映射時要留意性能問題。 在探索最佳實踐的過程中,應用的單元測試和性能測試會是你的好幫手。 而 MyBatis 的好處在于,可以在不對你的代碼引入重大變更(如果有)的情況下,允許你之后改變你的想法。
高級關聯(lián)和集合映射是一個深度話題。文檔的介紹只能到此為止。配合少許的實踐,你會很快了解全部的用法。
更多建議: