MyBatis框架之SQL對映和動態SQL

weixin_34054866發表於2018-06-20

使用MyBatis實現條件查詢

1.SQL對映檔案:

MyBatis真正的強大之處就在於SQL對映語句,MyBatis專注於SQL,對於開發人員來說也是極大限度的進行SQL調優,以保證效能。下面是SQL對映檔案的幾個頂級元素的配置:

1.mapper:對映檔案的根節點,只有一個屬性namespace(名稱空間),作用如下:

    (1)用於區分不同的mapper,全域性唯一。

    (2)繫結DAO介面,即面向介面程式設計,當繫結一個介面,就不用寫此介面的實現類,會通過介面的完全限定名找到對應的mapper配置來執行SQL語句,所以,namespace的命名必須要寫介面的完全限定名。

    2.cache:配置給定名稱空間的快取。

    3.cache-ref:從其他名稱空間引用快取配置。

    4.resultMap:用來描述資料庫結果集和物件的對應關係。

    5.sql:可以重用的SQL塊,也可以被其他語句引用。

    6.insert:對映插入語句。

    7.update:更新對映語句。

    8.delete:刪除對映語句。

    9.select:對映查詢語句。

2.使用select完成單條件查詢

<select id = "GetUserByName" resultType = "User" parameterType = "string">

  select * from user where name like concat('%',#{name},'%')    //按照姓名模糊查詢。

</select>

    這是一個id為GetUserByName的對映語句,引數型別為string,返回型別為User。

#{引數名}:告訴MyBatis生成的PreparedStatement引數,相對於JDBC,改引數被標識為‘?’。

  id:名稱空間的唯一識別符號,可以被用來引用這條語句。

  parameterType:表示查詢語句傳入引數的型別和完全限定名或別名。支援基礎資料型別和複雜資料型別。上述例項中傳入的引數是一個別名,代表String。

                 別名與Java型別對映

別名       對映的型別     別名     對映的型別    
string   String double Double
byte Byte float Float
long  Long boolean Boolean
short Short date Date
int Integer map Map
integer Integer hashmap HashMap
arraylist ArrayList list List

  resultType:查詢語句返回結果型別的完全限定名或別名。別名使用方式和parameterType是一樣的。

2.使用select完成多條件查詢

  使用複雜資料型別,把條件引數封裝為物件、Map進行入參。

  不管什麼型別的引數,或者多少個引數,都可以封裝為一個Map進行入參,通過Map的key進行獲取傳入的值。

1<select id="GetUserByNameAndRoleId" resultType="User"
2    parameterType="map">
3    select * from smbms_user where userName like
4    CONCAT('%',#{userName},'%')
5    and userRole = #{userRole}
6</select>

3.使用resultMap完成查詢結果的展現

    resultMap:做自定義對映,實體類屬性名和資料庫列名不一致的情況下,並且可以指定要顯示的列,使用靈活 應用廣泛。

1<resultMap type="User" id="userMap">
2  <id column="id" property="id"/>
3   <result column="userName" property="Name"/> //欄位名和屬性名不一致的情況下。
4</resultMap>

屬性和子節點:

    id:唯一標識,此id值用於select元素resultMap屬性的引用。

    type:標識該resultMap的對映結果型別。

    result子節點:標識一些簡單屬性,其中column屬性代表資料庫的欄位名,property代表查詢出來的欄位名對映到pojo類的某個屬性。   

    id子節點:與result子節點作用一樣,一般表示資料庫的主鍵列。

-------------------------------------------------------------------------------------------------------

resultType和resultMap的對比如下 :

1.resultType:直接表示返回型別, 包括基本資料型別和複雜資料型別。

2.resultMap:外部resultMap定義的引用,通過對應的外部resultMap的id,表示結果對映到哪個resultMap上,一般用於欄位名和屬性名不一致的情況,或者需要做複雜的聯合查詢以便自由控制對映結果。

3.兩者的關聯

    當進行查詢時,查詢出來的每個欄位都會放在一個Map裡,當查詢元素返回屬性是resultType的時候,會將鍵值對取出賦所指定的屬性。其實MyBatis的每個查詢對映的返回型別都是resultMap,只是當我們使用resultType的時候,會自動把對應的值賦給所指定的物件屬性,當使用resultMap時候,因為map不是很好的表示領域,我們就進一步的轉化為對應的實體物件。resultMap主要作用於複雜的聯合查詢上。

注意:resultType和resultMap本質是一樣的,都是Map資料結構,但是二者不能同時存在。

4.resultMap的自動對映級別:預設級別為PARTIAL,也可以在settings更改值。

1<settings>
2    <!-- 設定resultMap的自動對映級別為NONE(禁止自動匹配) -->
3    <setting name = "autoMappingBehavior" value = "NONE">
4</settings>

4.使用MyBatis實現增刪改操作

1.使用insert完成增加操作

<insert id="add" parameterType="User">
    INSERT INTO user(userName,userCode) VALUES(#{userName},#{userCode})</insert>

2.使用update完成修改操作

<update id="update" parameterType="User">

        UPDATE user SET userName= #{userName},userCode= #{userCode} WHERE id = #{id}    

</update>

3.使用delete完成刪除操作

<delete id="User" parameterType="integer">
        delete from user
        where id = #{id}
</delete>

元素中的屬性:

    id:與select元素id一樣,名稱空間的唯一識別符號。

    parameterType:傳入引數的型別的完全限定名或者別名。

對於增刪改操作的注意事項:

    (1)該型別的操作本身預設返回執行SQL影響的行數,所以DAO層的介面方法返回值一般為int型別,最好不要boolean型別。

    (2)insert、update、delete元素中均沒有resultType屬性,只有查詢操作需要對返回結果型別(resultType/resultMap)進行相應的指定。

 5.使用@param註解實現多引數入參

    使用註解用來傳入多個引數,相當於給該引數重新命名,在SQL對映檔案中需要使用#{註解名稱}來傳入引數。 

public user GetUserByIdAndName(@Param("id") Integer id,@Param("Name") String Name);

    當引數為基礎型別時,無論是多引數還是單引數,都使用@param註解進行引數的傳遞為好!

使用resultMap實現高階結果對映

1.association:

    對映到JavaBean的某個複雜的”資料型別”屬性,僅處理一對一的關聯關係。

association的屬性節點:

    property:對映資料庫列的實體物件屬性名。

    javaType:完整的java類名和限定名。propert所對映的屬性的型別。

    子元素:id:一般為對映主鍵,可以提高效能。

    result:

        column:對映的資料庫的欄位名。

        property:對映的資料列對應的實體物件屬性。
2.collection:

   對映到JavaBean的某個複雜的”資料型別”屬性,這個屬性是一個集合列表,處理一對多的關聯關係。

    ofType:完整的java類名和限定名。propert所對映的屬性的型別。

    其餘和association基本一致。

MyBatis快取

    1.一級快取:基於PerpetualCache(MyBatis自帶)的HashMap本地快取。作用域在Session域內,當session flush或者close之後,該快取被清空。

    2.二級快取:global Cache,超出session範圍之外,可以被所有SqlSession共享。開啟它只需在MyBatis的核心配置檔案 settings 設定即可。

    補充:一級快取快取的是SQL語句,二級快取快取的是結果物件。

    3.二級快取配置:

    (1)開啟二級快取;

<settings>
        <setting name="cacheEnabled" value = "true"/>
<settings>

    (2)mapper檔案中設定快取,預設是沒有開啟快取的。作用域是針對namespace而言的,只在namespace內的查詢才能共享這個cache。

    (3)對個別查詢進行快取,單獨設定cache:

<select id = "getUser" resultType = "User" useCache = "true">
    ...........
</select>

    補充:對MyBatis的快取瞭解就可以了,對結果集做快取並不是MyBatis所擅長的,而且效能也不是很好,它專心做的應該是SQL對映。

-----------------------------------------------------------------------------------------------------------------------

動態SQL

一、使用動態SQL完成多條件查詢。

    動態SQL基於OGNL的表示式,我們可以方便的在SQL語句中實現某些邏輯,用於實現動態SQL元素如下:

  if:利用if實現簡單的條件選擇。

  choose(when,otherwise):相當於java中的switch語句,通常與when和otherwise搭配。

  set:解決動態更新語句。

  trim:靈活的去除多餘的關鍵字。

  foreach:迭代一個集合,通常用於in條件。

二、if+where實現多條件查詢

    where元素可以智慧的處理and 和 or 的多餘問題, 不需擔心多餘關鍵字導致語法錯誤。

if元素的test用於判斷表示式是否符合,符合則繼續拼接SQL語句。

三、if+trim+foreach實現多條件查詢

(1)trim的屬性:

    prefix:字首: 作用是通過自動識別是否有返回值後,在trim包含的內容上加上字首,如上述示例的where。

    suffix:字尾: 作用是在trim包含的內容上加上字尾。

    prefixOverrides: 對於trim包含內容的首部進行指定內容,(如上述示例的 and | or) 的忽略(去餘);

    suffixOverrides: 對於trim包含內容的首位部進行指定內容的忽略。

(2)foreach的屬性:

    item:表示集合中每一個元素進行迭代時的別名。

    index: 指定一個名稱,表示在迭代的過程中,每次迭代到的位置。

    open:表示該語句以什麼開始(既然是in條件語句,必然是 ' ( ' 開始)

    separator: 表示每次進行迭代的時候以什麼符號作為分隔符(既然是in條件語句,必然是 ' , ' 分隔)

    close: 表示該語句以什麼結束(既然是in條件語句,必然是 ' ) ' 結束)

    collection:最關鍵,並且最容易出錯的屬性。需注意,該屬性必須指定,不同情況下,該屬性值是不同的,主要有三種情況:

    若傳入的引數是單引數且型別為一個List的時候,屬性值為list;

    若傳入的引數是單引數且型別為一個陣列的時候,屬性值為array;

    若傳入的引數為多引數時,就需要封裝為一個map集合進行處理。屬性值為Map的key;

 

使用set更新操作,類似於上述示例使用方法:

三、choose(when、otherwise)

    when元素:當test屬性中的條件滿足時,就會輸出when元素中的內容,並且當when中一旦有條件滿足時,就會跳出choose,所以只有一個條件會被輸出。

    otherwise元素:當when中的所有條件都不滿足時,則會輸出此元素的內容。

四、MyBatis實現分頁功能

    1.使用聚合函式獲得總記錄數-

    2.實現分頁通過limit(起始位置,頁面顯示量)

補充:起始位置的下標  = (當前頁碼 - 1 ) * 頁面顯示量

相關文章