MyBatis框架之SQL映射和動態SQL


使用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的某個復雜的”數據類型”屬性,僅處理一對一的關聯關系。

  <resultMap type="SMS_USER" id="userMap">
        <id column="id" property="id" />
        <result column="userName" property="userName" />
        <result column="phone" property="phone" />
        <association property="role" javaType="SMS_Role">
            <id column="id" property="id" />
            <result column="roleName" property="roleName" />
        </association>
    </resultMap>

   association的屬性節點:

    property:映射數據庫列的實體對象屬性名。

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

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

        result:

          column:映射的數據庫的字段名。

          property:映射的數據列對應的實體對象屬性。
2.collection:

   映射到JavaBean的某個復雜的”數據類型”屬性,這個屬性是一個集合列表,處理一對多的關聯關系。

    <resultMap type="SMS_USER" id="userMapAddress">
        <id column="id" property="id"/>
        <result column="userName" property="userName"/>
        <collection property="lists" ofType="SMS_Address">
       <id column = "id" property = "id"> <result column="addressDesc" property="addressDesc"/> </collection> </resultMap>

  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實現多條件查詢

    <select id="ShowUser" parameterType="Map" resultType="SMS_USER">
        select * from smbms_user
            <where>
                <if test="userRole != null and userRole != 0">
                    userRole = #{userRole}
                </if>
                <if test="userName != null and userName != ''">
                    and userName like CONCAT('%',#{userName},'%')
                </if>
            </where>
    </select>

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

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

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

 1  <select id="listsByInAndGender" resultType="SMS_USER">
 2           select * from smbms_user
 3         <trim prefix="where" prefixOverrides="and | or">
 4             <if test="userIds!=null">
 5                 id in
 6                 <foreach collection="userIds" item="ids" open="(" close=")" separator=",">
 7                     #{ids}
 8                 </foreach>
 9             </if>
10             <if test="gender != null and gender != 0">
11                 and gender = #{gender}
12             </if>
13         </trim>
14  </select>

(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更新操作,類似於上述示例使用方法:

 1     <update id="UpdateUser" parameterType="SMS_USER">
 2          update smbms_user
 3          <trim prefix="set" suffixOverrides="," suffix="where id = #{id}">
 4              <if test="userName != null and userName != ''">
 5                  userName = #{userName},
 6              </if>
 7              <if test="gender != null and gender != 0">
 8                  gender = #{gender},
 9              </if>
10              <if test="address != null and address != ''">
11                  address = #{address},
12              </if>
13          </trim>
14     </update>

 

三、choose(when、otherwise)

 1     <select id="QueryAllByChoose" resultType="SMS_provider">
 2         select * from smbms_provider where 1 = 1
 3         <choose>
 4             <when test="proCode != null and proCode != ''">
 5                 and proCode like CONCAT('%',#{proCode},'%')
 6             </when>
 7             <when test="proName != null and proName != ''">
 8                 and proName like CONCAT('%',#{proName},'%')
 9             </when>
10             <when test="proContact != null and proContact != ''">
11                 and proContact like CONCAT('%',#{proContact},'%')
12             </when>
13             <otherwise>
14                 and YEAR(creationDate) = 2016
15             </otherwise>
16         </choose>
17     </select>

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

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

四、MyBatis實現分頁功能

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

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

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

 1       <!-- 多條件篩選分頁 -->
 2     <select id="UserPage" parameterType="map" resultType="SMS_USER">
 3         select * from smbms_user
 4         <trim prefix="where" prefixOverrides="and | or">
 5             <if test="userName != null and userName != ''">
 6                 userName like concat('%',#{userName},'%')
 7             </if>
 8             <if test="userRole != null and userRole != 0">
 9                 and userRole = #{userRole}
10             </if>
11         </trim>
12         limit #{startRow},#{pageSize}
13     </select>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM