MyBatis 完全使用指南

發表於2016-11-25

MyBatis 完全使用指南
MyBatis作為一個輕量的SQL對映框架,確實很簡單,但是知識點挺多,實際使用中還是會有時想不起來某個標籤該怎麼寫,所以整理了這篇文章,以備查詢。由於MyBatis如此簡單,使得這一篇文章基本把實際使用中常碰到的事情都涵蓋了,包括:

  1. MyBatis中的一些概念
  2. MyBatis包含的內容
  3. SQL對映
  4. 動態SQL

一、 MyBatis中的一些概念

MyBatis 完全使用指南

MyBatis的架構

1. MyBatis是個什麼東西

在使用MyBatis的專案裡,日誌中往往會出現很多拼接SQL語句的log,這其實說明了MyBatis底層還是使用JDBC來實現的。在JDBC的基礎上,為了效能考慮,所有的語句都是基於SqlSession。顧名思義,維護這個類的例項其實就是維護了一個對於某個資料庫的連線的會話,在這個會話裡可以有快取啊什麼之類的。

2. mapper介面是怎麼對映成SQL語句的

目前多數開發者還是會使用XML來進行MyBatis的配置,包括MyBatis的核心配置和SQL對映配置。其實和註解一樣,XML本身只不過是一個後設資料的載體,最終起作用的還是MyBatis的核心類。其中有這樣幾個比較重要的:

  1. SqlSessionFactoryBuilder,用來建立SqlSessionFactory的例項,之後就沒有用了,其生命週期只是在初始化的時候有作用。
  2. SqlSessionFactory,MyBatis最基礎的類,用來建立會話(即SqlSession的例項),其生命週期與整個系統的生命週期相同,在系統執行的任何時候都可以使用它查詢到當前資料庫的配置資訊等。
  3. SqlSession,真正的和資料庫之間的會話,執行緒不安全,所以其生命週期和使用它的執行緒相同。
  4. 各種Mapper,承載了實際的業務邏輯,其生命週期比較短,由SqlSession建立。

3. Spring環境中MyBatis的初始化過程

實際情況中MyBatis往往是在Spring的環境中使用的,MyBatis本身並不依賴Spring,但是使用Spring可以極大的提高開發效率,由於Spring進行了控制反轉,所以其中MyBatis的初始化過程和正常過程稍稍有些不同:

  1. Spring發現需要建立SqlSessionFactory例項,會在classpath下找到MyBatis的核心配置檔案,使用它來初始化一個SqlSessionFactory例項。當然,這一步完全可以使用程式碼來完成,或者使用註解,就更加清晰明瞭。
  2. 往往mapper類也會作為bean注入到程式碼中去的,那麼Spring會使用上一步中的SqlSessionFactory例項來建立SqlSession的例項。
  3. 然後再使用SqlSession嘗試建立各個mapper物件。
  4. 於此同時,MyBatis會掃描classpath下的mapper對映XML檔案(此路徑可以自定義),對於每一個mapper介面,它的「類全名」會作為名稱空間,來和對映檔案中的mapper標籤進行匹配。
  5. 對於每一個對映檔案中的一個執行語句標籤(如select、delete),MyBatis會把他們對映到SqlSession的方法上,建立mapper介面的一個實現類。
  6. 如果mapper介面和其對映檔案一一匹配,則bean建立成功。

二、MyBatis包含的內容

MyBatis本身就是一個簡單的ORM框架,提供了SQL語句到方法、關係型資料表到物件的對映。實際使用中與開發者相關的有兩個東西:

  1. MyBatis核心配置
    快取、資料來源、日誌等關係到MyBatis其本身行為的一些配置。
  2. mapper介面的對映
    針對於具體業務邏輯的SQL對映。

三、SQL對映

MyBatis也可以使用註解來實現對映,對於簡單的語句,使用註解可能會更加清晰簡單,但是其真正強大的地方還是XML。

1. select

屬性 描述
id 此名稱空間內的識別符號
parameterType 引數的類的全名或者alias,可選。預設為空。
parameterMap Deprecated
resultType 返回結果的型別全名或alias,如果結果是集合,此型別表示的是集合的成員型別。
resultMap 使用指定的resultMap來對映結果集。resultMap 和 resultType只能二選一。
flushCache 如果為true,每次呼叫,一級快取和二級快取都會回寫。select語句中預設為false。
useCache 如果為true,結果將在二級快取中快取。select語句中預設為true
timeout 設定超時,若超時則丟擲異常。
fetchSize 嘗試在獲取資料時分批獲取。
statementType STATEMENT,PREPARED或者CALLABLE. 分別對應JDBC中的Statement,PreparedStatement和CallableStatement respectively。預設PREPARED.
resultSetType FORWARD_ONLY,SCROLL_SENSITIVE或者SCROLL_INSENSITIVE。預設為空。
databaseId 使用特定的databaseIdProvider
resultOrdered 巢狀查詢時使用。
resultSets 多返回集合時使用。

2. 修改語句(insert,update,DELETE)

這3種語句的屬性基本和上邊select的一樣,INSERT和UPDATE的語句有幾個特殊的屬性如下:

屬性 描述
useGeneratedKeys 將使用JDBC的getGeneratedKeys方法來獲取主鍵的值。預設為false。
keyProperty 主鍵。MyBatis會將生成的主鍵賦給這個列。聯合主鍵使用逗號隔開。
keyColumn 特定資料庫需要使用。

3. SQl語句段(sql標籤)

標籤可以定義一段sql語句段,可以在其他語句中引入使用。sql標籤可以包含引數。示例如下:

引數(property)也可以在refid或者include進來的sql中使用。示例如下:

4. #{}${}的區別

  1. #{}在底層實現上使用?做佔位符來生成PreparedStatement,然後將引數傳入,大多數情況都應使用這個,它更快、更安全。
  2. ${}將傳入的資料直接顯示生成在sql中。如:order by ${user_id},如果傳入的值是111,那麼解析成sql時的值為order by 111, 如果傳入的值是id,則解析成的sql為order by id.

5. 型別別名

什麼地方都少不了這種小技巧,可以讓你少打很多字。

6. ResultMap

官方文件上說這個特性是整個MyBatis中最強大的特性(沒有之一)。其實它做的就是對映結果集。

MyBatis底層使用JDBC,所以查詢出來的結果是ResultSet,如果resultType是一個物件,MyBatis底層就會建立一個resultMap,並根據欄位名一一對應上這個物件。如果你有一個查詢,它的結果集非常複雜,可以使用resultMap來做對映。

cache和cach-ref

使用cache標籤在對映檔案內(某名稱空間內)實現二級快取,其所有屬性都有預設值,所以單單一個標籤就可以生效。cach-ref可以在兩個對映檔案之間共享快取

四、動態SQL

1. if

條件判斷,引數為test

2. choose (巢狀when,otherwise)

多選一,引數為test

3. trim (where,set)

  • trim標籤可以定製其他標籤,並且去頭去尾;
  • where標籤會自動生成where語句,並且可以去除頭部的and或者or;
  • set標籤可以自動生成set語句,並且可以去除尾部的逗號。

4. foreach

迴圈集合輸出,可以迴圈陣列,Iterable物件,或者Map,如果是Map,則index會是key。

5. bind

宣告一個使用OGNL表示式生成的變數,在sql語句中使用。