MyBatis 3 結(jié)果映射-集合

2022-04-09 14:40 更新

集合

<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>

集合元素和關(guān)聯(lián)元素幾乎是一樣的,它們相似的程度之高,以致于沒(méi)有必要再介紹集合元素的相似部分。 所以讓我們來(lái)關(guān)注它們的不同之處吧。

我們來(lái)繼續(xù)上面的示例,一個(gè)博客(Blog)只有一個(gè)作者(Author)。但一個(gè)博客有很多文章(Post)。 在博客類(lèi)中,這可以用下面的寫(xiě)法來(lái)表示:

private List<Post> posts;

要像上面這樣,映射嵌套結(jié)果集合到一個(gè) List 中,可以使用集合元素。 和關(guān)聯(lián)元素一樣,我們可以使用嵌套 Select 查詢,或基于連接的嵌套結(jié)果映射集合。

集合的嵌套 Select 查詢

首先,讓我們看看如何使用嵌套 Select 查詢來(lái)為博客加載文章。

<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>

你可能會(huì)立刻注意到幾個(gè)不同,但大部分都和我們上面學(xué)習(xí)過(guò)的關(guān)聯(lián)元素非常相似。 首先,你會(huì)注意到我們使用的是集合元素。 接下來(lái)你會(huì)注意到有一個(gè)新的 “?ofType?” 屬性。這個(gè)屬性非常重要,它用來(lái)將 ?JavaBean?(或字段)屬性的類(lèi)型和集合存儲(chǔ)的類(lèi)型區(qū)分開(kāi)來(lái)。 所以你可以按照下面這樣來(lái)閱讀映射:

<collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>

讀作: “posts 是一個(gè)存儲(chǔ) Post 的 ArrayList 集合”

在一般情況下,MyBatis 可以推斷 ?javaType ?屬性,因此并不需要填寫(xiě)。所以很多時(shí)候你可以簡(jiǎn)略成:

<collection property="posts" column="id" ofType="Post" select="selectPostsForBlog"/>

集合的嵌套結(jié)果映射

現(xiàn)在你可能已經(jīng)猜到了集合的嵌套結(jié)果映射是怎樣工作的——除了新增的 “?ofType?” 屬性,它和關(guān)聯(lián)的完全相同。

首先, 讓我們看看對(duì)應(yīng)的 SQL 語(yǔ)句:

<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>

我們?cè)俅芜B接了博客表和文章表,并且為每一列都賦予了一個(gè)有意義的別名,以便映射保持簡(jiǎn)單。 要映射博客里面的文章集合,就這么簡(jiǎn)單:

<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 元素的重要性,如果你不記得了,請(qǐng)閱讀關(guān)聯(lián)部分的相關(guān)部分。

如果你喜歡更詳略的、可重用的結(jié)果映射,你可以使用下面的等價(jià)形式:

<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>

集合的多結(jié)果集(ResultSet)

像關(guān)聯(lián)元素那樣,我們可以通過(guò)執(zhí)行存儲(chǔ)過(guò)程實(shí)現(xiàn),它會(huì)執(zhí)行兩個(gè)查詢并返回兩個(gè)結(jié)果集,一個(gè)是博客的結(jié)果集,另一個(gè)是文章的結(jié)果集:

SELECT * FROM BLOG WHERE ID = #{id}

SELECT * FROM POST WHERE BLOG_ID = #{id}

在映射語(yǔ)句中,必須通過(guò) ?resultSets ?屬性為每個(gè)結(jié)果集指定一個(gè)名字,多個(gè)名字使用逗號(hào)隔開(kāi)。

<select id="selectBlog" resultSets="blogs,posts" resultMap="blogResult">
  {call getBlogsAndPosts(#{id,jdbcType=INTEGER,mode=IN})}
</select>

我們指定 “posts” 集合將會(huì)使用存儲(chǔ)在 “posts” 結(jié)果集中的數(shù)據(jù)進(jìn)行填充:

<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>

對(duì)關(guān)聯(lián)或集合的映射,并沒(méi)有深度、廣度或組合上的要求。但在映射時(shí)要留意性能問(wèn)題。 在探索最佳實(shí)踐的過(guò)程中,應(yīng)用的單元測(cè)試和性能測(cè)試會(huì)是你的好幫手。 而 MyBatis 的好處在于,可以在不對(duì)你的代碼引入重大變更(如果有)的情況下,允許你之后改變你的想法。

高級(jí)關(guān)聯(lián)和集合映射是一個(gè)深度話題。文檔的介紹只能到此為止。配合少許的實(shí)踐,你會(huì)很快了解全部的用法。



以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)