MyBatis 3 結果映射-集合

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>

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

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

private List<Post> posts;

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

集合的嵌套 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>

集合的多結果集(ResultSet)

像關聯(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)和集合映射是一個深度話題。文檔的介紹只能到此為止。配合少許的實踐,你會很快了解全部的用法。



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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號