以下是iBatis映射文件的一個簡單例子:
<?xml version="1.0"encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap>
<cacheModelid=”productCache” type=”LRU”>
<flushInterval hours="24"/>
<flushOnExecute statement="insertStudent"/>
<flushOnExecute statement="deleteStudentById"/>
<flushOnExecute statement="updateStudentById"/>
<property name=”size” value=”1000” />
</cacheModel>
<typeAlias alias="Student" type="com.edifier.data.Student"/>
<resultMap id="StudentResult" class="Student">
<resultproperty="sid" column="sid"/>
<resultproperty="sname" column="sname"/>
<resultproperty="major" column="major"/>
<resultproperty="birth" column="birth"/>
<resultproperty="sroce" column="sroce"/>
</resultMap>
<parameterMap id="StudentParameter" class=""Student"">
<parameterproperty="sid" jdbcType="int" javaType="int"/>
<parameterproperty="sname" jdbcType="varchar"javaType="String"/>
</parameterMap>
<select id="selectAllStudents" resultClass="Student" cacheModel=”product-cache”>
select
sid,sname,major,birth,score
from
student;
</select>
<select id="selectStudentById" parameterClass="int"resultClass="Student">
select
sid,sname,major,birth,score
from
student
where
sid= #sid#;
</select>
<insert id="insertStudent" parameterClass="Student">
insert into
student(sid,sname,major,birth,score)
values(#sid#,#sname#,#major#,#birth#,#score#);
</insert>
<delete id="deleteStudentById" parameterClass="int">
delete from
student
where
sid= #sid#;
</delete>
<update id="updateStudentById" parameterClass="student">
update student set
sname= #sname#,
major= #major#,
birth= #birth#,
score= #score#
wheresid = #sid#;
</update>
<!-- 模糊查詢這裏有兩種方式,第一種在sql中這樣寫 sname like #sname#, 代碼中這樣寫"%e%" 第二種是在sql中sname like '%$sname$%',代碼中這樣寫"e".-->
<select id="selectStudentByName" parameterClass="String"resultClass="Student">
select
sid,sname,major,birth,score
from
student
where
snamelike '%$sname$%';
</select>
<insert id="insertStudentBySequence" parameterClass="Student">
insert into
student(sname,major,birth,score)
values(#sname#,#major#,#birth#,#score#);
<!—Mysql中用到的-->
<selectKey resultClass="int"keyProperty="sid" >
SELECT @@IDENTITY AS SID
</selectKey>
<!--以下在Oracle中用到
<selectKey resultClass="int" keyProperty="sid">
select studentPKSequence.nextVal as sid from dual;
</selectKey>
-->
</insert>
</sqlMap>
在這個例子中,xml的DTD和SqlMapConfig.xml配置文件的不一樣要注意,不然會報錯。例子中包括了cacheModel、typeAlias、resultMap、parameterMap、以及增刪改,查詢全部、根據id查詢和模糊查詢。其中增刪改查都屬於statement元素,下表總結了statement 類型及其屬性:
Statement 類型 |
屬性 |
<statement> |
id parameterClass resultClass parameterMap resultMap cacheModel xmlResultName |
<insert> |
id parameterClass parameterMap |
<update> |
id parameterClass parameterMap |
<delete> |
id parameterClass parameterMap |
<select> |
id parameterClass resultClass parameterMap resultMap cacheModel |
<procedure> |
id parameterClass resultClass parameterMap resultMap xmlResultName |
SQL 語句
在statement元素中可以寫所有JDBC Driver所支持的sql語句。但是由於sql語句是鑲嵌在xml文檔中,所以有些特殊符號不能直接使用,例如:<、>。iBatis這裏給出瞭解決辦法。
<![CDATA[
select * from student score >#score#
]]>
自動生成的主鍵
iBatis中唯一使用了自動生成主鍵的就是<insert>元素,使用子元素<selectKey>來支持自動生成的主鍵。它同時支持預生成(如Oracle)和後生成(MySQL)。下面是兩個例子:
<!—OracleSEQUENCE Example -->
<insertid="insertStudent-ORACLE" parameterClass="com.edifier.Student">
<selectKey resultClass="int"keyProperty="id" >
SELECT STOCKIDSEQUENCE.NEXTVAL ASID FROM DUAL
</selectKey>
insert into Student (SID,SName)
values (#id#,#name#)
</insert>
<!—Microsoft SQL Server IDENTITY Column Example -->
<insert id=" insertStudent-MS-SQL" parameterClass="com. edifier. Student">
insert into Student ( SName)
values (#name #)
<selectKey resultClass="int"keyProperty="id" >
SELECT @@IDENTITY AS ID
</selectKey>
</insert>
存儲過程
通過<procedure>元素支持存儲過程。下面的例子說明如何使用具有輸出參數的存儲過程。
<parameterMapid="swapParameters" class="map" >
<parameter property="email1"jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>
<parameter property="email2"jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>
</parameterMap>
<procedureid="swapEmailAddresses" parameterMap="swapParameters" >
{call swap_email_address (?, ?)}
</procedure>
調用上面的存儲過程將同時互換兩個字段(數據庫表)和參數對象(Map)中的兩個 email地址。如果參數的 mode 屬性設爲 INOUT 或 OUT,則參數對象的值被修改。否則保持不變。
parameterClass
parameterClass 屬性的值是 Java 類的全限定名(即包括類的包名)。parameterClass 屬性是可選的,但強烈建議使用。它的目的是限制輸入參數的類型爲指定的 Java 類,並優化框架的性能。如果您使用 parameterMap,則沒有必要使用 parameterClass 屬性。例如,如果要只允許 Java 類“com. edifier.Student”作爲輸入參數,可以這樣作:
<statementid=”statementName” parameterClass=” com. edifier.Student”>
insert into PRODUCT values (#id#, #name#, #score#)
</statement>
parameterMap
屬性 parameterMap 的值等於一個預先定義的<parameterMap>元素的名稱。parameterMap屬性很少使用,更多的是使用上面的 parameterClass 和 inline parameter(接下來會討論)。parameterMap 的基本思想是定義一系列有次序的參數系列,用於匹配 JDBC PreparedStatement的值符號。例如:
<parameterMapid=”insert-student -param” class=”com. edifier. Student”>
<parameter property=”id”/>
<parameter property=” name”/>
</parameterMap>
<statementid=”insertStudent” parameterMap=”insert- student -param”>
insert into Student (SID, SNAME) values(?,?);
</statement>
上面的例子中,parameter map 的兩個參數按次序匹配 SQL 語句中的值符號(?)。因此,第一個“?”號將被“id”屬性的值替換,而第二個“?”號將被“name”屬性的值替換。
Inline Parameter簡介
現在簡單介紹一下 inline parameter,詳細討論見後面章節。Inline parameter 可以嵌在
mappedstatement 內部使用。例如:
<statementid=”insertStudent” >
insert into Student(SID, SNAME)
values (#id#, #name#);
</statement>
以上例子中,內嵌的參數是#id#和#name#。每個參數代表一個 Java Bean 屬性,用於給 SQL 語句中相應的位置賦值。上面例子中,Student 對象的 id 和 description 屬性的值將會替換 SQL 語句中相應的符號。因此,對於 id=5,name=‘Steven’的Student 對象,SQL語句變爲:
insert into Student (SID, SNAME) values (5, ‘Steven’);
resultClass
resultClass 屬性的值是 Java 類的全限定名(即包括類的包名)。resultClass 屬性可以讓您指定一個 Java 類,根據 ResultSetMetaData 將其自動映射到 JDBC 的 ResultSet。只要是 JavaBean 的屬性名稱和 ResultSet 的列名匹配,屬性自動賦值給列值。這使得查詢 mappedstatement變得很短。例如:
<statementid="getPerson" parameterClass=”int” resultClass="com.edifier.Person">
SELECT PER_ID as id,
PER_FIRST_NAME as firstName,
PER_LAST_NAME as lastName,
PER_BIRTH_DATE as birthDate,
PER_WEIGHT_KG as weightInKilograms,
PER_HEIGHT_M as heightInMeters
FROM PERSON
WHERE PER_ID = #value#
</statement>
在上面的例子中,Person 類擁有屬性包括 id,firstName,lastName,birthDate,weightInKilograms和 heightInMeters。每一個屬性對應 SQL 查詢語句一個列的別名(使用“as”關鍵字-標準的 SQL 語法)。一般情況下,列名和屬性名稱不匹配,就需要使用“as”關鍵字。當執行 mapped statement 時,Person 類將被初始化,從結果集中得到的列值將根據屬性名和列名映射成 Person 對象的屬性值。正如以前所說,使用 resultClass 的自動映射存在一些限制,無法指定輸出字段的數據類型(如果需要的話),無法自動裝入相關的數據(複雜屬性),並且因爲需要 ResultSetMetaData的信息,會對性能有輕微的不利影響。但使用 resultMap,這些限制都可以很容易解決。
resultMap
resultMap 是最常用和最重要的屬性。ResultMap 屬性的值等於預先定義的 resultMap 元素的 name 屬性值(參照下面的例子)。使用 resultMap 可以控制數據如何從結果集中取出,以及哪一個屬性匹配哪一個字段。不象使用 resultClass 的自動映射方法,resultMap 屬性可以允許指定字段的數據類型,NULL 的替代值複雜類型映射(包括其他 Java Bean,集合類型和基本類型包裝類)。關於 resultMap 的詳細討論放在以後的章節,這裏只給出一個相關 statement 的 resultMap的例子。
<resultMapid=”get-student-result” class=”com.edifier.Student”>
<result property=”id” column=”SID”/>
<result property=”name” column=”SNAME”/>
</resultMap>
<statementid=”getStudent” resultMap=”get- student -result”>
select * from Student
</statement>
上面的例子中,通過 resultMap 的定義,查詢語句得到的 ResultSet 被映射成Student對象。resultMap 定義的“id”屬性值將賦予“SID”字段值,而“name”屬性值將賦予“SNAME”字段值。注意 resultMap 支持“select *”,並不要求定義 ResultSet所有返回字段的映射。
cacheModel
cacheModel 的屬性值等於指定的 cacheModel 元素的 name 屬性值。屬性 cacheModel 定義查詢 mapped statement 的緩存。每一個查詢 mapped statement 可以使用不同或相同的cacheModel。以下只給出個例子。
<cacheModelid="student-cache" imlementation="LRU">
<flushInterval hours="24"/>
<flushOnExecute statement="insertStudent"/>
<flushOnExecute statement="deleteStudentById"/>
<flushOnExecute statement="updateStudentById"/>
<property name=”size” value=”1000” />
</cacheModel>
<statementid=”selectAllStudent” parameterClass=”int” cacheModel=”product-cache”>
select sid,sname,major,birth,score from student;
</statement>
上面例子中,“selectAllStudent”的緩存使用 WEAK 引用類型,每 24 小時刷新一次,或當更新的操作發生時刷新。
Cache的類型有以下幾種:
“MEMORY”(com.ibatis.db.sqlmap.cache.memory.MemoryCacheController)
“LRU”(com.ibatis.db.sqlmap.cache.lru.LruCacheController) --Least Recently Used
“FIFO”(com.ibatis.db.sqlmap.cache.fifo.FifoCacheController) --First In First Out
“OSCACHE”(com.ibatis.db.sqlmap.cache.oscache.OSCacheController)
1.MEMORY 編碼結構:
<cacheModel id="student-cache"type="MEMORY">
<flushInterval hours="24"/>
<flushOnExecute statement="insertStudent"/>
<flushOnExecute statement="deleteStudentById"/>
<flushOnExecute statement="updateStudentById"/>
<property name=”reference-type”value=”WEAK” />
</cacheModel>
取不到對象再利用的identifiable pattern或者應用程序的內存不足的時候選用。
reference-type的值可以是下面的3個:
WEAK (default) |
當別的對象要用內存的時候,可以毫無保留的釋放自己的內存。 |
SOFT |
當別的對象需要內存的時候,有可能不會釋放自己的內存。 |
STRONG |
cache時間到達以前,肯定不會釋放內存。小的靜態的經常被使用的區域可以使用這個選項。缺點是如果內存不足也不會釋放內存。 |
2.LRU 編碼結構:
<cacheModel id="student-cache"type="LRU">
<flushInterval hours="24"/>
<flushOnExecute statement="insertStudent"/>
<flushOnExecute statement="deleteStudentById"/>
<flushOnExecute statement="updateStudentById"/>
<property name=”size” value=”1000” />
</cacheModel>
應用程序的一部分內容經常被多人多次使用的時候選用。
3.FIFO 編碼結構:
<cacheModel id="student-cache"type="FIFO">
<flushInterval hours="24"/>
<flushOnExecute statement="insertStudent"/>
<flushOnExecute statement="deleteStudentById"/>
<flushOnExecute statement="updateStudentById"/>
<property name=”size” value=”1000” />
</cacheModel>
連續的短時間的參照,以後就再不參照的時候選用。
4.OSCACHE 編碼結構:
<cacheModel id="student-cache"type="OSCACHE">
<flushInterval hours="24"/>
<flushOnExecute statement="insertStudent"/>
<flushOnExecute statement="deleteStudentById"/>
<flushOnExecute statement="updateStudentById"/>
</cacheModel>
屬性名 |
說明 |
cache.memory |
cache放在內存中,false的話放在硬盤裏 |
cache.key |
ServletContext中存放cache的key名 |
cache.capacity |
存放的大小(這個一直不知道單位是什麼,配置文件裏寫的是條數,我怎麼感覺設成50都能顯示1000個) |
cache.path |
cache保存的路徑 |
cache.unlimited.disk |
無限cache,默認是false,這時候就會有限制,參照cache.capacity來分配硬盤空間 |