溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

MyBatis 之Result Maps最精華部分

發(fā)布時(shí)間:2020-09-20 12:22:05 來源:網(wǎng)絡(luò) 閱讀:589 作者:sun2shadows 欄目:軟件技術(shù)

案例:https://github.com/sun2shadow/simpleMybatis

resultMap 元素是 MyBatis 中最重要最強(qiáng)大的元素。

先看一個(gè)簡單的映射:

<select id="selectUsers" resultType="map">
  select id, username, hashedPassword
  from some_table
  where id = #{id}
</select>

它把所有的列映射到HashMap的主鍵上.但是實(shí)踐中經(jīng)常把resultType類型制定為JavaBeans或POJOs,如以下語句:

<select id="selectUsers" resultType="com.someapp.model.User">
  select id, username, hashedPassword
  from some_table
  where id = #{id}
</select>

高級映射是開發(fā)中常用的形式:

resultMap概念視圖:

  • constructor - 類在實(shí)例化時(shí),用來注入結(jié)果到構(gòu)造方法中

    • idArg - ID 參數(shù);標(biāo)記結(jié)果作為 ID 可以幫助提高整體效能

    • arg - 注入到構(gòu)造方法的一個(gè)普通結(jié)果

  • id – 一個(gè) ID 結(jié)果;標(biāo)記結(jié)果作為 ID 可以幫助提高整體效能

  • result – 注入到字段或 JavaBean 屬性的普通結(jié)果

  • association – 一個(gè)復(fù)雜的類型關(guān)聯(lián);許多結(jié)果將包成這種類型

    • 嵌入結(jié)果映射 – 結(jié)果映射自身的關(guān)聯(lián),或者參考一個(gè)

  • collection – 復(fù)雜類型的集

    • 嵌入結(jié)果映射 – 結(jié)果映射自身的集,或者參考一個(gè)

  • discriminator – 使用結(jié)果值來決定使用哪個(gè)結(jié)果映射

    • 嵌入結(jié)果映射 – 這種情形結(jié)果也映射它本身,因此可以包含很多相                      同的元素,或者它可以參照一個(gè)外部的結(jié)果映射。

    • case – 基于某些值的結(jié)果映射

ResultMap Attributes
屬性描述
id當(dāng)前命名空間中的一個(gè)唯一標(biāo)識,用于標(biāo)識一個(gè)result map.
type類的全限定名, 或者一個(gè)類型別名 (內(nèi)置的別名可以參考上面的表格).
autoMapping如果設(shè)置這個(gè)屬性,MyBatis將會為這個(gè)ResultMap開啟或者關(guān)閉自動映射。這個(gè)屬性會覆蓋全局的屬性autoMappingBehavior。默認(rèn)值為:unset。
<resultMap id="detailedBlogResultMap" type="Blog">
</resultMap>

Id&result

<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>

id 和 result 都映射一個(gè)單獨(dú)列的值到簡單數(shù)據(jù)類型(字符 串,整型,雙精度浮點(diǎn)數(shù),日期等)的單獨(dú)屬性或字段

Id and Result Attributes
屬性描述
property映射到列結(jié)果的字段或?qū)傩?。如果匹配的是存在?和給定名稱相同 的 JavaBeans 的屬性,那么就會使用。否則 MyBatis 將會尋找給定名稱 property 的字段。這兩種情形你可以使用通常點(diǎn)式的復(fù)雜屬性導(dǎo)航。比如,你 可以這樣映射一些東西: “username” ,或者映射到一些復(fù)雜的東西: “address.street.number” 。
column從數(shù)據(jù)庫中得到的列名,或者是列名的重命名標(biāo)簽。這也是通常和會 傳遞給 resultSet.getString(columnName)方法參數(shù)中相同的字符串。
javaType一個(gè) Java 類的完全限定名,或一個(gè)類型別名(參考上面內(nèi)建類型別名 的列表) 。如果你映射到一個(gè) JavaBean,MyBatis 通??梢詳喽愋?。 然而,如果你映射到的是 HashMap,那么你應(yīng)該明確地指定 javaType 來保證所需的行為。
jdbcType在這個(gè)表格之后的所支持的 JDBC 類型列表中的類型。JDBC 類型是僅 僅需要對插入,更新和刪除操作可能為空的列進(jìn)行處理。這是 JDBC jdbcType 的需要,而不是 MyBatis 的。如果你直接使用 JDBC 編程,你需要指定 這個(gè)類型-但僅僅對可能為空的值。
typeHandler我們在前面討論過默認(rèn)的類型處理器。使用這個(gè)屬性,你可以覆蓋默 認(rèn)的類型處理器。這個(gè)屬性值是類的完全限定名或者是一個(gè)類型處理 器的實(shí)現(xiàn),或者是類型別名。

關(guān)聯(lián):連表查詢時(shí)需要關(guān)聯(lián)映射關(guān)系.property:blog中author變量,column表的author的外建,javaType關(guān)聯(lián)的entity

<association property="author" column="blog_author_id" javaType="Author">
  <id property="id" column="author_id"/>
  <result property="username" column="author_username"/>
</association>

通過映射關(guān)系來告訴MyBatis如何加載關(guān)聯(lián)關(guān)系,MyBatis提供了2中方式:

  • 嵌套查詢:通過執(zhí)行另外一個(gè) SQL 映射語句來返回預(yù)期的復(fù)雜類型。

  • 嵌套結(jié)果:使用嵌套結(jié)果映射來處理重復(fù)的聯(lián)合結(jié)果的子集。首先,然讓我們來查看這個(gè)元素的屬性。所有的你都會看到,它和普通的只由 select 和

resultMap 屬性的結(jié)果映射不同。

關(guān)聯(lián)的嵌套查詢:

<resultMap id="blogResult" type="Blog">
  <association property="author" column="author_id" javaType="Author" select="selectAuthor"/>
</resultMap>
<select id="selectBlog" resultMap="blogResult">
  SELECT * FROM BLOG WHERE ID = #{id}
</select>
<select id="selectAuthor" resultType="Author">
  SELECT * FROM AUTHOR WHERE ID = #{id}
</select>

一個(gè)來加載博客,另外一個(gè)來加載作者,這種方式最大的問題就是N+1查詢問題,查詢一條博客有N個(gè)作者需要查詢作者表N次.

關(guān)聯(lián)的嵌套結(jié)果:

先看一個(gè)這樣的語句:查詢blog的作者和聯(lián)合作者,作者和聯(lián)合作者的id不能都叫author_id,否則會引起沖突.

<select id="selectBlog" resultMap="blogResult">
  select
    B.id            as blog_id,
    B.title         as blog_title,
    A.id            as author_id,
    A.username      as author_username,
    A.password      as author_password,
    A.email         as author_email,
    A.bio           as author_bio,
    CA.id           as co_author_id,
    CA.username     as co_author_username,
    CA.password     as co_author_password,
    CA.email        as co_author_email,
    CA.bio          as co_author_bio
  from Blog B
  left outer join Author A on B.author_id = A.id
  left outer join Author CA on B.co_author_id = CA.id
  where B.id = #{id}</select>

首先定義author的結(jié)果映射:

<resultMap id="authorResult" type="Author">
  <id property="id" column="author_id"/>
  <result property="username" column="author_username"/>
  <result property="password" column="author_password"/>
  <result property="email" column="author_email"/>
  <result property="bio" column="author_bio"/>
</resultMap>

其次定義blog的resultMap,通過columnPrefix來指定前綴以此來區(qū)分是主作者還是聯(lián)合作者.

<resultMap id="blogResult" type="Blog">
  <id property="id" column="blog_id" />
  <result property="title" column="blog_title"/>
  <association property="author" resultMap="authorResult" />
  <association property="coAuthor" resultMap="authorResult" columnPrefix="co_" />
</resultMap>

看完了關(guān)聯(lián),再來看集合就容易多了,基本上是相似的.

private List<Post> posts;

這種關(guān)系就需要用到集合,通過ofType指定,列表內(nèi)數(shù)據(jù)的類型是Post.

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

上面這個(gè)查詢需要映射的關(guān)系如下:collection 中property屬性是blog中的變量posts,看上面的變量聲明

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

下面來簡單的說明一下鑒別器:根據(jù)查詢結(jié)果的不同來選擇不同的映射器.

鑒別器這個(gè)例子比較有意思,查詢車輛信息,返回不同類型的車輛,有轎車,貨車,SUV等不同類型有不同的映射結(jié)果.

<resultMap id="vehicleResult" type="Vehicle">
  <id property="id" column="id" />
  <result property="vin" column="vin"/>
  <result property="year" column="year"/>
  <result property="make" column="make"/>
  <result property="model" column="model"/>
  <result property="color" column="color"/>
  <discriminator javaType="int" column="vehicle_type">
    <case value="1" resultMap="carResult"/>
    <case value="2" resultMap="truckResult"/>
    <case value="3" resultMap="vanResult"/>
    <case value="4" resultMap="suvResult"/>
  </discriminator>
</resultMap>

如果類型是car的話,則按照carResult來映射結(jié)果:

<resultMap id="carResult" type="Car">
  <result property="doorCount" column="door_count" />
</resultMap>

這種情況下只有 doorCount 屬性會被加載.如果 Car 是一個(gè) Vehicle 實(shí)例。因此,我們想要剩余的屬性也被加載。我們設(shè)置的結(jié)果映射的 簡單改變?nèi)缦隆?/p>

<resultMap id="carResult" type="Car" extends="vehicleResult">
  <result property="doorCount" column="door_count" />
</resultMap>


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI