mybatis的SQL對映配置檔案
SQL對映檔案有很少的幾個頂級元素(按照他們應該被定義的順序如下)。
- cache - 配置給定名稱空間的快取
- cache-ref – 從其他名稱空間引用快取配置。
- resultMap – 最複雜,也是最有力量的元素,用來描述如何從資料庫結果集中來載入你的物件。
- parameterMap – 已經被廢棄了!老式風格的引數對映。內聯引數是首選,這個元素可能在將來被移除。
- sql – 可以重用的SQL塊,也可以被其他語句引用。
- insert – 對映插入語句
- update – 對映更新語句
- delete -對映刪除語句
- select - 對映查詢語句
SELECT
簡單的SELECT 語句如下:
SELECT * FROM PERSON WHERE ID = #{id}
</select>
這個語句被稱作selectPerson,使用一個int (或Integer)型別的引數,並返回一個HashMap型別的物件
#{id}告訴mybatis建立了一個PreparedStatement(預處理語句)引數。在JDBC中,類似的程式碼如下
寫道 String selectPerson = “SELECT * FROM PERSON WHERE ID=?”;PreparedStatement ps = conn.prepareStatement(selectPerson);
ps.setInt(1,id);
SELECT的屬性還有很多的屬性可以配置,具體的如下:
- id 在名稱空間中唯一的識別符號,可以被用來引用這條語句。
- parameterType 將會傳入這條語句的引數類的完全限定名或別名。
- resultType 從這條語句中返回的期望型別的類的完全限定名或別名。注意集合情形,那應該是集合可以包含的型別,而不能是集合本身。使用resultType或resultMap,但不能同時使用。
- resultMap 命名引用外部的resultMap。返回map是MyBatis最具力量的特性,對其有一個很好的理解的話,許多複雜對映的情形就能被解決了。使用resultMap 或resultType,但不能同時使用
- flushCache 將其設定為true,無論語句什麼時候被呼叫,都會導致快取被清空。預設值:false。
- useCache 將其設定為true,將會導致本條語句的結果被快取。預設值:true。
- timeout 這個設定驅動程式等待資料庫返回請求結果,並丟擲異常時間的最大等待值。預設不設定(驅動自行處理)。
- fetchSize 這是暗示驅動程式每次批量返回的結果行數。預設不設定(驅動自行處理)。
- statementType STATEMENT,PREPARED或CALLABLE的一種。這會讓MyBatis使用選擇使用Statement,PreparedStatement或CallableStatement。預設值:PREPARED。
- resultSetType FORWARD_ONLY|SCROLL_SENSITIVE|SCROLL_INSENSITIVE中的一種。預設是不設定(驅動自行處理)。
insert,update,delete
資料修改語句insert,update和delete在它們的實現中非常相似。
寫道
<insertid="insertAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
keyProperty=""
useGeneratedKeys=""
timeout="20000">
SQL
這個元素可以被用來定義可重用的SQL程式碼段,可以包含在其他語句中,例如
寫道 <sql id=”userColumns”> id,username,password </sql>這個SQL片段可以被包含在其他語句中,例如:
<select id=”selectUsers” parameterType=”int” resultType=”hashmap”>
select <include refid=”userColumns”/>
from some_table
where id = #{id}
</select>
Parameters
這個元素說的直白點就是定義引數。注意一個語句中只能有一個引數。所以引數型別在以後的使用中,可能需要複雜的型別,比如hashmap,一個複雜的物件等。例如:
寫道 <insert id=”insertUser” parameterType=”User” >insert into users (id, username, password)
values (#{id}, #{username}, #{password})
</insert>
如果User型別的引數物件傳遞到了語句中,id、username和password屬性將會被查詢,
然後它們的值就被傳遞到預處理語句的引數中。
resultMap
resultMap 元素是MyBatis中最重要最強大的元素。它就是讓你遠離90%的需要從結果集中取出資料的JDBC程式碼的那東西,而且在一些情形下允許你做一些JDBC不支援的事情。事實上,編寫相似於對複雜語句聯合對映這些等同的程式碼,也許可以跨過上千行的程式碼。ResultMap的設計就是簡單語句不需要明確的結果對映,而很多複雜語句確實需要描述它們的關係。
寫道 <select id=”selectUsers” parameterType=”int” resultType=”hashmap”>select id, username, hashedPassword
from some_table
where id = #{id}
</select>
這個語句查詢出來的所有列將會自動對映到HashMap的鍵上,這個是由resultType的屬性來指定的。但是HashMap不能很好描述一個領域模型。那樣你的應用程式將會使用JavaBeans或POJO 來作為領域模型。
例如一個javabean如下
Java程式碼- package com.someapp.model;
- publicclass User {
- privateint id;
- private String username;
- private String hashedPassword;
- //set和get方法。。。。
- }
package com.someapp.model;
public class User {
private int id;
private String username;
private String hashedPassword;
//set和get方法。。。。
}
寫道
<select id=”selectUsers” parameterType=”int” resultType=”com.some app.model.User”>
select id, username, hashedPassword
from some_table
where id = #{id}
</select>
當然在使用的時候可以不用輸入全名,只需在XML的配置檔案中進行以下設定。
寫道 <!-- 在XML配置檔案中--><typeAlias type=”com.some app.model.User” alias=”User”/>
<!-- 在SQL對映的XML檔案中-->
<select id=”selectUsers” parameterType=”int”
resultType=”User”>
select id, username, hashedPassword
from some_table
where id = #{id}
</select>
快取
MyBatis包含一個非常強大的查詢快取特性,它可以非常方便地配置和定製。預設情況下是沒有開啟快取的,除了區域性的session 快取。要開啟二級快取,你需要在你的SQL對映檔案中新增一行: <cache/>
這個簡單語句的效果如下:
1 對映語句檔案中的所有select語句將會被快取。
2 對映語句檔案中的所有insert,update和delete語句會重新整理快取。
3 快取會使用Least Recently Used(LRU,最近最少使用的)演算法來收回。
4 根據時間表(比如no Flush Interval,沒有重新整理間隔),快取不會以任何時間順序來重新整理。
5 快取會儲存列表集合或物件(無論查詢方法返回什麼)的1024個引用。
6 快取會被視為是read/write(可讀/可寫)的快取,意味著物件檢索不是共享的,而且可以安全地被呼叫者修改,而不干擾其他呼叫者或執行緒所做的潛在修改。
一個簡單的例項如下
寫道 <cacheeviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
這個配置建立了一個FIFO快取,並每隔60秒重新整理,存數結果物件或列表的512個引用,而且返回的物件被認為是隻讀的,因此在不同執行緒中的呼叫者之間修改它們會導致衝突。
可用的收回策略有:
- LRU – 最近最少使用的:移除最長時間不被使用的物件。
- FIFO – 先進先出:按物件進入快取的順序來移除它們。
- SOFT – 軟引用:移除基於垃圾回收器狀態和軟引用規則的物件。
- WEAK – 弱引用:更積極地移除基於垃圾收集器狀態和弱引用規則的物件。 預設的是LRU。
flushInterval(重新整理間隔)可以被設定為任意的正整數,而且它們代表一個合理的毫秒形式的時間段。預設情況是不設定,也就是沒有重新整理間隔,快取僅僅呼叫語句時重新整理。
size(引用數目)可以被設定為任意正整數,要記住你快取的物件數目和你執行環境的可用記憶體資源數目。預設值是1024。
readOnly(只讀)屬性可以被設定為true 或false。只讀的快取會給所有呼叫者返回快取物件的相同例項。因此這些物件不能被修改。這提供了很重要的效能優勢。可讀寫的快取會返回快取物件的拷貝(通過序列化)。這會慢一些,但是安全,因此預設是false。
動態SQL
動態SQL的元素有以下幾個:
if choose(when,otherwise) trim(where,set) foreach
if
寫道 <select id=”findActiveBlogWithTitleLike”parameterType=”Blog” resultType=”Blog”>
SELECT * FROM BLOG
WHERE state = „ACTIVE‟
<if test=”title != null”>
AND title like #{title}
</if>
</select>
choose, when, otherwise
有時我們不想應用所有的條件,相反我們想選擇很多情況下的一種。和Java中的switch語句相似,MyBatis提供choose元素。
寫道 <select id=”findActiveBlogLike”parameterType=”Blog” resultType=”Blog”>
SELECT * FROM BLOG WHERE state = „ACTIVE‟
<choose>
<when test=”title != null”>
AND title like #{title}
</when>
<when test=”author != null and author.name != null”>
AND title like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
trim, where, set
寫道 <select id=”findActiveBlogLike”parameterType=”Blog” resultType=”Blog”>
SELECT * FROM BLOG
WHERE
<if test=”state != null”>
state = #{state}
</if>
<if test=”title != null”>
AND title like #{title}
</if>
<if test=”author != null and author.name != null”>
AND title like #{author.name}
</if>
</select>
如果這些條件都沒有匹配上將會發生什麼?這條SQL結束時就會成這樣:
SELECT * FROM BLOG WHERE,從而導致查詢失敗。
如果僅僅第二個條件匹配,這條SQL結束時就會是這樣:
SELECT * FROM BLOG WHERE AND title like
MyBatis有一個簡單的處理,這在90%的情況下都會有用。而在不能使用的地方,你可以自定義處理方式。加上一個簡單的改變,所有事情都會順利進行:
寫道 <select id=”findActiveBlogLike”parameterType=”Blog” resultType=”Blog”>
SELECT * FROM BLOG
<where>
<if test=”state != null”>
state = #{state}
</if>
<if test=”title != null”>
AND title like #{title}
</if>
<if test=”author != null and author.name != null”>
AND title like #{author.name}
</if>
</ where >
</select>
where元素知道如果由被包含的標記返回任意內容,就僅僅插入“WHERE”。而且,如果以“AND”或“OR”開頭的內容,那麼就會跳過WHERE不插入。
foreach
另外一個動態SQL通用的必要操作是迭代一個集合,通常是構建在IN條件中的
寫道 <select id="selectPostIn" resultType="domain.blog.Post">SELECT *
FROM POST P
WHERE ID in
<foreac h ite m="item" inde x="index" c ollection="list"
open="(" separator="," close=")">
#{item}
</fore ach>
</select>
foreach 元素是非常強大的,它允許你指定一個集合,宣告集合項和索引變數,它們可以用在元素體內。它也允許你指定開放和關閉的字串,在迭代之間放置分隔符。