1. 程式人生 > >mybatis的SQL對映配置檔案

mybatis的SQL對映配置檔案

SQL對映檔案有很少的幾個頂級元素(按照他們應該被定義的順序如下)。

  • cache -  配置給定名稱空間的快取
  • cache-ref –  從其他名稱空間引用快取配置。 
  • resultMap –  最複雜,也是最有力量的元素,用來描述如何從資料庫結果集中來載入你的物件。
  • parameterMap –  已經被廢棄了!老式風格的引數對映。內聯引數是首選,這個元素可能在將來被移除。
  • sql –  可以重用的SQL塊,也可以被其他語句引用。
  • insert –  對映插入語句 
  • update –  對映更新語句 
  • delete -對映刪除語句
  • select - 對映查詢語句

SELECT

簡單的SELECT 語句如下:

 寫道 <select id=”selectPerson” parameterType=”int” resultType=”hashmap”>
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在它們的實現中非常相似。

寫道

<insert
id="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程式碼  
  1. package com.someapp.model;   
  2. publicclass User {   
  3. privateint id;   
  4. private String username;   
  5. private String hashedPassword;   
  6. //set和get方法。。。。
  7. }  
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(可讀/可寫)的快取,意味著物件檢索不是共享的,而且可以安全地被呼叫者修改,而不干擾其他呼叫者或執行緒所做的潛在修改。

一個簡單的例項如下

 寫道 <cache
eviction="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 元素是非常強大的,它允許你指定一個集合,宣告集合項和索引變數,它們可以用在元素體內。它也允許你指定開放和關閉的字串,在迭代之間放置分隔符。