使用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>