MyBatis常用動态标簽大全見上述URL,它們大概分為如下四類:
标簽 | 作用 | 使用場景 |
foreach | 循環語句 | 批量添加或者批量查詢 |
if | 條件判斷語句 | 單條件分支判斷 |
choose、when、otherwise | 類似 Java 中的 switch、case、default 語句 | 多條件分支判斷 |
trim、where、set | 輔助标簽 | 用于處理一些條件查詢 |
在MyBatis中有一個ResultMap标簽,它是為了映射select标簽查詢出來的結果集,其主要作用是将實體類中的字段與資料庫表中的字段進行關聯映射。
前言
Mybatis 中 select 标簽有兩個屬性 resultType 和 resultMap,用于在mapper.xml檔案中配置傳回結果類型,工作中經常使用到它們。那麼在日常開發中,應該如何正确的選擇呢?下面我們對這兩個屬性分别進行講解和示範。
結果類型resultType
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
resultMap 直譯就是結果映射,該元素是 MyBatis 中最重要最強大的元素。與 resultType 相比,resultMap就要強大許多,它不僅能夠用于簡單查詢,還能用于級聯查詢以及設定緩存,功能可謂是十分的強大。它可以讓你從 90% 的 JDBC ResultSets 資料提取代碼中解放出來,并在一些情形下允許你進行一些 JDBC 不支援的操作。實際上,在為一些比如連接配接的複雜語句編寫映射代碼的時候,一份 resultMap 能夠代替實作同等功能的數千行代碼。ResultMap 的設計思想是,對簡單的語句做到零配置,對于複雜一點的語句,隻需要描述語句之間的關系就行了。溫馨提示:resultType 和 resultMap 之間隻能同時使用一個。
resultMap标簽屬性
resultMap 标簽的屬性值包括兩個:
id 屬性:唯一辨別,此 id 值用于 select 标簽 resultMap 屬性的引用。
type 屬性:表示該 resultMap 的映射結果類型,可以為類的全限定名或者别名。
resultMap子标簽包括如下幾個 :
子标簽 | 功能 | 備注 |
id | 指定查詢列中的唯一辨別,如果有多個列組成唯一辨別,配置多個id | 可以不用 |
result | 用于辨別一些簡單屬性,包括column和property兩個屬性 | 常用 |
association | 在主表的pojo中嵌套另一個表的pojo | 不推薦使用 |
collection | 把查詢到的多條記錄映射到集合對象 | 不推薦使用 |
result标簽的屬性包括兩個:
- column:資料庫字段名或别名。
- property:實體類中的屬性,和column屬性一一對應。
resultMap使用示例
下面使用一個簡單的例子,來介紹 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>
resultType和resultMap的差別
下面了解一下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官網。
當你遇到這個話題的時候,你通常怎麼了解呢?你碰到過特别精彩、讓人印象深刻的回答嗎?歡迎大家積極留言交流。