摘要:介紹MyBatis 中Select標籤的兩個屬性resultType和resultMap及其區別。
1 MyBatis動態SQL之if 語句
2 MyBatis動態sql之where標籤|轉
3 MyBatis動態SQL之set標籤|轉
4 MyBatis動態SQL之trim元素|轉
5 MyBatis動態sql中foreach標籤的使用
6 MyBatis動態SQL之choose(when、otherwise)語句
7 MyBatis動態SQL之bind標籤|轉
8 MyBatis標籤之Select resultType和resultMap
MyBatis常用動態標籤大全見上述URL,它們大概分為如下四類:
標籤 | 作用 | 使用場景 |
---|---|---|
foreach | 迴圈語句 | 批次新增或者批次查詢 |
if | 條件判斷語句 | 單條件分支判斷 |
choose、when、otherwise | 類似 Java 中的 switch、case、default 語句 | 多條件分支判斷 |
trim、where、set | 輔助標籤 | 用於處理一些條件查詢 |
在MyBatis中有一個ResultMap標籤,它是為了對映select標籤查詢出來的結果集,其主要作用是將實體類中的欄位與資料庫表中的欄位進行關聯對映。
Mybatis 中 select 標籤有兩個屬性 resultType 和 resultMap,用於在mapper.xml檔案中設定返回結果型別,工作中經常使用到它們。那麼在日常開發中,應該如何正確的選擇呢?下面我們對這兩個屬性分別進行講解和演示。
resultType直譯就是結果的型別,可以設定為期望從select 語句中返回結果的類的全限定名或別名。resultType使用場景如下:
如果查詢結果只是返回一個值,比如返回String、map或int,那麼可以使用resultType指定簡單型別作為輸出結果。
我們先了解一個resultType的簡單對映語句範例,它沒有顯式地指定 resultMap
。比如:
<sql id="resultTypeColumn">
id, username, hashedPassword
</sql>
<select id="selectUsers" resultType="map">
select
<include refid="resultTypeColumn"/>
from some_table
where id = #{id}
</select>
上述語句只是簡單地將所有的列對映到 HashMap
的鍵上,這由 resultType
屬性指定。此處對查詢欄位用了一個 sql 標籤進行封裝,該sql 片段可複用。
還有一種情況就是如果資料庫表的欄位名和實體bean物件的屬性名一樣。 雖然在大部分情況下都夠用,但是 HashMap 並不是一個很好的領域模型;你的程式更可能會使用 JavaBean 或 POJO(普通老式 Java 物件)作為領域模型,MyBatis 對兩者都提供了支援。看看下面這個 JavaBean:
package com.someapp.model;
public class User {
private int id;
private String username;
private String hashedPassword;
// omit getter,setter and toString
}
基於 JavaBean 的規範,上面這個類有 3 個屬性:id,username 和 hashedPassword,它們會對應到 select 語句中的列名。這樣的一個 JavaBean 可以被對映到 ResultSet
,就像對映到 HashMap
一樣簡單。
<select id="selectUsers" resultType="com.someapp.model.User">
select
<include refid="resultTypeColumn"/>
from some_table
where id = #{id}
</select>
型別別名是你的好幫手,關於如何設定型別別名,請移步《Spring Boot MyBatis使用type-aliases-package自定義類別名》。使用別名後就可以不用輸入類的全限定名了。譬如:
<select id="selectUsers" resultType="User">
select
<include refid="resultTypeColumn"/>
from some_table
where id = #{id}
</select>
在此情況下,MyBatis 會在幕後自動建立一個 resultMap
,再根據屬性名來對映列到 JavaBean 的屬性上。如果列名和屬性名不能匹配上,可以在 SELECT 語句中設定列別名(這是一個基本的 SQL 特性)來完成匹配。例如:
<sql id="resultTypeColumn">
user_id as "id",
user_name as "userName",
hashed_password as "hashedPassword"
</sql>
<select id="selectUsers" resultType="map">
select
<include refid="resultTypeColumn"/>
from some_table
where id = #{id}
</select>
注意,如果返回的是集合,那應該設定為集合包含的型別,而不是集合本身的型別。
resultMap
直譯就是結果對映,該元素是 MyBatis 中最重要最強大的元素。與 resultType 相比,resultMap就要強大許多,它不僅能夠用於簡單查詢,還能用於級聯查詢以及設定快取,功能可謂是十分的強大。它可以讓你從 90% 的 JDBC ResultSets
資料提取程式碼中解放出來,並在一些情形下允許你進行一些 JDBC 不支援的操作。實際上,在為一些比如連線的複雜語句編寫對映程式碼的時候,一份 resultMap
能夠代替實現同等功能的數千行程式碼。ResultMap 的設計思想是,對簡單的語句做到零設定,對於複雜一點的語句,只需要描述語句之間的關係就行了。溫馨提示:resultType 和 resultMap 之間只能同時使用一個。
resultMap 標籤的屬性值包括兩個:
id 屬性:唯一標識,此 id 值用於 select 標籤 resultMap 屬性的參照。
type 屬性:表示該 resultMap 的對映結果型別,可以為類的全限定名或者別名。
resultMap子標籤包括如下幾個 :
子標籤 | 功能 | 備註 |
---|---|---|
id | 指定查詢列中的唯一標識,如果有多個列組成唯一標識,設定多個id | 可以不用 |
result | 用於標識一些簡單屬性,包括column和property兩個屬性 | 常用 |
association | 在主表的pojo中巢狀另一個表的pojo | 不推薦使用 |
collection | 把查詢到的多條記錄對映到集合物件 | 不推薦使用 |
result標籤的屬性包括兩個:
下面使用一個簡單的例子,來介紹 resultMap 的使用方法。雖然上一節中的例子不用顯式設定 resultMap
,但為了講解,我們來看看如果顯式使用外部的 resultMap
會怎樣;這也是解決列名和bean名不匹配的另外一種方式。定義一個resultMap:
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="user_name"/>
<result property="password" column="hashed_password"/>
</resultMap>
然後在參照它的語句中設定 resultMap
屬性就行了(注意我們去掉了 resultType
屬性)。比如:
<select id="selectUsers" resultMap="userResultMap">
select user_id, user_name, hashed_password
from some_table
where id = #{id}
</select>
下面瞭解一下MyBatis中資料轉換機制:在進行查詢對映的時候,其實查詢出來的每一個屬性都是放在一個對應的Map裡面,其中鍵是屬性名,值則是其對應的值。當提供的返回型別屬性是resultType的時候,MyBatis會將Map裡面的鍵值對取出賦給resultType所指定的物件對應的屬性。所以,其實MyBatis的每一個查詢對映的返回型別都是ResultMap,只是當我們提供的返回型別屬性是resultType的時候,MyBatis自動的把對應的值賦給resultType所指定物件的屬性,而當提供的返回型別是resultMap的時候,因為Map不能很好表示領域模型,我們就需要自己把它轉化為對應的物件,這常常在複雜查詢中很有作用。
言歸正傳,resultType和resultMap到底有什麼區別呢?
resultType不需要設定,但是resultMap要設定一下。resultType是直接指定返回型別的,而使用resultMap時,需要在外部ResultMap標籤中,設定資料庫表的欄位名和實體bean物件類的屬性的一一對應關係。設定後,就算資料庫的欄位名和實體類的屬性名不一樣也沒有關係,mybatis依然會給對映出來,所以resultMap要更強大一些。
就像上面說的那樣,如果查詢出來資料庫欄位名(包括欄位別名)和要封裝的實體bean物件屬性值不相同時,只能使用resultMap來返回結果。
還有一個區別是resultMap可以用在複雜聯合查詢上,而resultType不可以。關於這一點,大家可以去Mybatis官網瞭解一下,這裡點到為止。
至此,大家已經瞭解了resultType和resultMap的基本用法,在日常業務開發中已經可以遊刃有餘了。如果想更上一層樓,掌握更多關於resultMap的高階用法,請移步Mybatis官網。
當你遇到這個話題的時候,你通常怎麼理解呢?你碰到過特別精彩、讓人印象深刻的回答嗎?歡迎大家積極留言交流。