天天看點

iBatis:O/R Mapping解決方案

j2ee的O/R方案真是多,和Hibernate相比,iBatis最大的特點就是小巧,上手很快。看iBatis的文檔2小時就會用了,這個O/R Mapping特點就是簡單易用。隻要有SQL基礎,相信你不用教程也能看明白。最新版本2.0(下載下傳)。

建構ibatis基礎代碼

ibatis 基礎代碼包括:

1. ibatis 執行個體配置

一個典型的配置檔案如下(具體配置項目的含義見後):

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE sqlMapConfig

PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"

"http://www.ibatis.com/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

<settings

cacheModelsEnabled="true"

enhancementEnabled="true"

lazyLoadingEnabled="true"

errorTracingEnabled="true"

maxRequests="32"

maxSessions="10"

maxTransactions="5"

useStatementNamespaces="false"

/>

<transactionManager type="JDBC">

IBATIS Developer’s Guide Version 1.0

September 2, 2004 So many open source projects. Why not Open your Documents?

<dataSource type="SIMPLE">

<property name="JDBC.Driver"

value="com.p6spy.engine.spy.P6SpyDriver"/>

<property name="JDBC.ConnectionURL"

value="jdbc:mysql://localhost/sample"/>

<property name="JDBC.Username" value="user"/>

<property name="JDBC.Password" value="mypass"/>

<property name="Pool.MaximumActiveConnections"

value="10"/>

<property name="Pool.MaximumIdleConnections" value="5"/>

<property name="Pool.MaximumCheckoutTime"

value="120000"/>

<property name="Pool.TimeToWait" value="500"/>

<property name="Pool.PingQuery" value="select 1 from

ACCOUNT"/>

<property name="Pool.PingEnabled" value="false"/>

<property name="Pool.PingConnectionsOlderThan"

value="1"/>

<property name="Pool.PingConnectionsNotUsedFor"

value="1"/>

</dataSource>

</transactionManager>

<sqlMap resource="com/ibatis/sample/User.xml"/>

</sqlMapConfig>

2. POJO(Plain Ordinary Java Object)

下面是我們用作示例的一個POJO:

public class User implements Serializable {

private Integer id;

private String name;

private Integer sex;

private Set addresses = new HashSet();

public User() {

}

public Integer getId() {

return this.id;

IBATIS Developer’s Guide Version 1.0

September 2, 2004 So many open source projects. Why not Open your Documents?

}

public void setId(Integer id) {

this.id = id;

}

public String getName() {

return this.name;

}

public void setName(String name) {

this.name = name;

}

public Integer getSex() {

return this.sex;

}

public void setSex(Integer sex) {

this.sex = sex;

}

}

3. 映射檔案

與Hibernate 不同。因為需要人工編寫SQL 代碼,ibatis 的映射檔案一般采

用手動編寫(通過Copy/Paste,手工編寫映射檔案也并沒想象中的麻煩)。

針對上面POJO 的映射代碼如下:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE sqlMap

PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"

" http://www.ibatis.com/dtd/sql-map-2.dtd">

<sqlMap namespace="User">

<typeAlias alias="user" type="com.ibatis.sample.User"/>

<select id="getUser"

parameterClass="java.lang.String"

resultClass="user">

<![CDATA[

select

name,

sex

from t_user

IBATIS Developer’s Guide Version 1.0

September 2, 2004 So many open source projects. Why not Open your Documents?

where name = #name#

]]>

</select>

<update id="updateUser"

parameterClass="user">

<![CDATA[

UPDATE t_user

SET

name=#name#,

sex=#sex#

WHERE id = #id#

]]>

</update>

<insert id="insertUser"

parameterClass="user"

>

INSERT INTO t_user (

name,

sex)

VALUES (

#name#,

#sex#

)

</insert>

<delete id="deleteUser"

parameterClass="java.lang.String">

delete from t_user

where id = #value#

</delete>

</sqlMap>

從上面的映射檔案可以看出,通過<insert>、<delete>、<update>、

<select>四個節點,我們分别定義了針對TUser 對象的增删改查操作。在這

四個節點中,我們指定了對應的SQL 語句,以update節點為例:

……

<update id="updateUser" ⑴

parameterClass="user"> ⑵

<![CDATA[ ⑶

UPDATE t_user ⑷

SET (

IBATIS Developer’s Guide Version 1.0

September 2, 2004 So many open source projects. Why not Open your Documents?

name=#name#, ⑸

sex=#sex# ⑹

)

WHERE id = #id# ⑺

]]>

</update>

……

⑴ ID

指定了操作ID,之後我們可以在代碼中通過指定操作id 來執行此節點所定

義的操作,如:

sqlMap.update("updateUser",user);

ID設定使得在一個配置檔案中定義兩個同名節點成為可能(兩個update節

點,以不同id區分)

⑵ parameterClass

指定了操作所需的參數類型, 此例中update 操作以

com.ibatis.sample.User 類型的對象作為參數,目标是将提供的User

執行個體更新到資料庫。

parameterClass="user"中,user為“com.ibatis.sample.User”

類的别名,别名可通過typeAlias節點指定,如示例配置檔案中的:

<typeAlias alias="user" type="com.ibatis.sample.User"/>

⑶ <![CDATA[……]]>

通過<![CDATA[……]]>節點,可以避免SQL 中與XML 規範相沖突的字元對

XML映射檔案的合法性造成影響。

⑷ 執行更新操作的SQL,這裡的SQL 即實際資料庫支援的SQL 語句,将由

ibatis填入參數後交給資料庫執行。

⑸ SQL中所需的使用者名參數,“#name#”在運作期會由傳入的user對象的name

屬性填充。

⑹ SQL 中所需的使用者性别參數“#sex#”,将在運作期由傳入的user 對象的

sex屬性填充。

⑺ SQL中所需的條件參數“#id#”,将在運作期由傳入的user對象的id屬性

填充。

對于這個示例,ibatis在運作期會讀取id 為“updateUser”的update節點

的SQL定義,并調用指定的user對象的對應getter方法擷取屬性值,并用此

屬性值,對SQL中的參數進行填充後送出資料庫執行。

此例對應的應用級代碼如下,其中示範了ibatis SQLMap的基本使用方法:

String resource ="com/ibatis/sample/SqlMapConfig.xml";

Reader reader;

IBATIS Developer’s Guide Version 1.0

September 2, 2004 So many open source projects. Why not Open your Documents?

reader = Resources.getResourceAsReader(resource);

XmlSqlMapClientBuilder xmlBuilder =

new XmlSqlMapClientBuilder();

SqlMapClient sqlMap = xmlBuilder.buildSqlMap(reader);

//sqlMap系統初始化完畢,開始執行update操作

try{

sqlMap.startTransaction();

User user = new User();

user.setId(new Integer(1));

user.setName("Erica");

user.setSex(new Integer(1));

sqlMap.update("updateUser",user);

sqlMap.commitTransaction();

finally{

sqlMap.endTransaction();

}

其中,SqlMapClient是ibatis運作的核心,所有操作均通過SqlMapClient

執行個體完成。

可以看出,對于應用層而言,程式員面對的是傳統意義上的資料對象,而非JDBC

中煩雜的ResultSet,這使得上層邏輯開發人員的工作量大大減輕,同時代碼更

加清晰簡潔。

資料庫操作在映射檔案中加以定義,進而将資料存儲邏輯從上層邏輯代碼中獨立

出來。

而底層資料操作的SQL可配置化,使得我們可以控制最終的資料操作方式,通過

SQL的優化獲得最佳的資料庫執行效能,這在依賴SQL自動生成的“全自動”ORM

機制中是所難以實作的。

IBATIS Developer’s Guide Version 1.0

September 2, 2004 So many open source projects. Why not Open your Documents?

ibatis配置

結合上面示例中的ibatis配置檔案。下面是對配置檔案中各節點的說明:

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE sqlMapConfig

PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"

" http://www.ibatis.com/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

<settings ⑴

cacheModelsEnabled="true"

enhancementEnabled="true"

lazyLoadingEnabled="true"

errorTracingEnabled="true"

maxRequests="32"

maxSessions="10"

maxTransactions="5"

useStatementNamespaces="false"

/>

<transactionManager type="JDBC"> ⑵

<dataSource type="SIMPLE"> ⑶

<property name="JDBC.Driver"

value="com.p6spy.engine.spy.P6SpyDriver"/>

<property name="JDBC.ConnectionURL"

value="jdbc:mysql://localhost/sample"/>

<property name="JDBC.Username" value="user"/>

<property name="JDBC.Password" value="mypass"/>

<property name="Pool.MaximumActiveConnections"

value="10"/>

<property name="Pool.MaximumIdleConnections" value="5"/>

<property name="Pool.MaximumCheckoutTime"

value="120000"/>

<property name="Pool.TimeToWait" value="500"/>

<property name="Pool.PingQuery" value="select 1 from

ACCOUNT"/>

<property name="Pool.PingEnabled" value="false"/>

<property name="Pool.PingConnectionsOlderThan"

value="1"/>

<property name="Pool.PingConnectionsNotUsedFor"

value="1"/>

</dataSource>

IBATIS Developer’s Guide Version 1.0

September 2, 2004 So many open source projects. Why not Open your Documents?

</transactionManager>

<sqlMap resource="com/ibatis/sample/User.xml"/> ⑷

<sqlMap resource="com/ibatis/sample/Address.xml"/>

</sqlMapConfig>

⑴ Settings 節點

參數 描述

cacheModelsEnabled 是否啟用SqlMapClient上的緩存機制。

建議設為"true"

enhancementEnabled 是否針對POJO啟用位元組碼增強機制以提升

getter/setter的調用效能,避免使用Java

Reflect所帶來的性能開銷。

同時,這也為Lazy Loading帶來了極大的性能

提升。

建議設為"true"

errorTracingEnabled 是否啟用錯誤日志,在開發期間建議設為"true"

以友善調試

lazyLoadingEnabled 是否啟用延遲加載機制,建議設為"true"

maxRequests 最大并發請求數(Statement并發數)

maxTransactions 最大并發事務數

maxSessions 最大Session 數。即目前最大允許的并發

SqlMapClient數。

maxSessions設定必須介于

maxTransactions和maxRequests之間,即

maxTransactions<maxSessions=<

maxRequests

useStatementNamespaces 是否使用Statement命名空間。

這裡的命名空間指的是映射檔案中,sqlMap節點

的namespace屬性,如在上例中針對t_user

表的映射檔案sqlMap節點:

<sqlMap namespace="User">

這裡,指定了此sqlMap節點下定義的操作均從

屬于"User"命名空間。

在useStatementNamespaces="true"的情

況下,Statement調用需追加命名空間,如:

IBATIS Developer’s Guide Version 1.0

September 2, 2004 So many open source projects. Why not Open your Documents?

sqlMap.update("User.updateUser",use

r);

否則直接通過Statement名稱調用即可,如:

sqlMap.update("updateUser",user);

但請注意此時需要保證所有映射檔案中,

Statement定義無重名。

⑵ transactionManager節點

transactionManager 節點定義了ibatis 的事務管理器,目前提供了以下幾

種選擇:

Ø JDBC

通過傳統JDBC Connection.commit/rollback實作事務支援。

Ø JTA

使用容器提供的JTA服務實作全局事務管理。

Ø EXTERNAL

外部事務管理,如在EJB中使用ibatis,通過EJB的部署配置即可實作自

動的事務管理機制。此時ibatis 将把所有事務委托給外部容器進行管理。

此外,通過Spring 等輕量級容器實作事務的配置化管理也是一個不錯的選

擇。關于結合容器實作事務管理,參見“進階特性”中的描述。

⑶ dataSource節點

dataSource從屬于transactionManager節點,用于設定ibatis運作期使

用的DataSource屬性。

type屬性: dataSource節點的type屬性指定了dataSource的實作類型。

可選項目:

Ø SIMPLE:

SIMPLE是ibatis内置的dataSource實作,其中實作了一個簡單的

資料庫連接配接池機制, 對應ibatis 實作類為

com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory。

Ø DBCP:

基于Apache DBCP 連接配接池元件實作的DataSource 封裝,當無容器提

供DataSource 服務時,建議使用該選項,對應ibatis 實作類為

com.ibatis.sqlmap.engine.datasource.DbcpDataSourceFactory。

Ø JNDI:

使用J2EE 容器提供的DataSource 實作,DataSource 将通過指定

的JNDI Name 從容器中擷取。對應ibatis 實作類為

com.ibatis.sqlmap.engine.datasource.JndiDataSourceFacto

ry。

dataSource的子節點說明(SIMPLE&DBCP):

IBATIS Developer’s Guide Version 1.0

September 2, 2004 So many open source projects. Why not Open your Documents?

參數 描述

JDBC.Driver JDBC 驅動。

如:org.gjt.mm.mysql.Driver

JDBC.ConnectionURL 資料庫URL。

如:jdbc:mysql://localhost/sample

如果用的是SQLServer JDBC Driver,需要

在url後追加SelectMethod=Cursor以獲得

JDBC事務的多Statement支援。

JDBC.Username 資料庫使用者名

JDBC.Password 資料庫使用者密碼

Pool.MaximumActiveConn

ections

資料庫連接配接池可維持的最大容量。

Pool.MaximumIdleConnec

tions

資料庫連接配接池中允許的挂起(idle)連接配接數。

以上子節點适用于SIMPLE 和DBCP 模式,分别針對SIMPLE 和DBCP 模式的

DataSource私有配置節點如下:

SIMPLE:

參數 描述

Pool.MaximumCheckoutTi

me

資料庫聯接池中,連接配接被某個任務所允許占用的

最大時間,如果超過這個時間限定,連接配接将被強

制收回。(毫秒)

Pool.TimeToWait 當線程試圖從連接配接池中擷取連接配接時,連接配接池中無

可用連接配接可供使用,此時線程将進入等待狀态,

直到池中出現空閑連接配接。此參數設定了線程所允

許等待的最長時間。(毫秒)

Pool.PingQuery 資料庫連接配接狀态檢測語句。

某些資料庫在連接配接在某段時間持續處于空閑狀态

時會将其斷開。而連接配接池管理器将通過此語句檢

測池中連接配接是否可用。

檢測語句應該是一個最簡化的無邏輯SQL。

如“select 1 from t_user”,如果執行此語句

成功,連接配接池管理器将認為此連接配接處于可用狀态。

Pool.PingEnabled 是否允許檢測連接配接狀态。

Pool.PingConnectionsOl

derThan

對持續連接配接時間超過設定值(毫秒)的連接配接進行

檢測。

IBATIS Developer’s Guide Version 1.0

September 2, 2004 So many open source projects. Why not Open your Documents?

Pool.PingConnectionsNo

tUsedFor

對空閑超過設定值(毫秒)的連接配接進行檢測。

DBCP:

參數 描述

Pool.MaximumWait 當線程試圖從連接配接池中擷取連接配接時,連接配接池中無

可用連接配接可供使用,此時線程将進入等待狀态,

直到池中出現空閑連接配接。此參數設定了線程所允

許等待的最長時間。(毫秒)

Pool.ValidationQuery 資料庫連接配接狀态檢測語句。

某些資料庫在連接配接在某段時間持續處于空閑狀态

時會将其斷開。而連接配接池管理器将通過此語句檢

測池中連接配接是否可用。

檢測語句應該是一個最簡化的無邏輯SQL。

如“select 1 from t_user”,如果執行此語句

成功,連接配接池管理器将認為此連接配接處于可用狀态。

Pool.LogAbandoned 當資料庫連接配接被廢棄時,是否列印日志。

Pool.RemoveAbandonedTi

meout

資料庫連接配接被廢棄的最大逾時時間

Pool.RemoveAbandoned 當連接配接空閑時間超過

RemoveAbandonedTimeout時,是否将其廢

棄。

JNDI由于大部配置設定置是在應用伺服器中進行,是以ibatis中的配置相對簡單,下面

是分别使用JDBC和JTA事務管理的JDNI配置:

使用JDBC事務管理的JNDI DataSource配置

<transactionManager type="JDBC" >

<dataSource type="JNDI">

<property name="DataSource"

value="java:comp/env/jdbc/myDataSource"/>

</dataSource>

</transactionManager>

<transactionManager type="JTA" >

<property name="UserTransaction"

value="java:/ctx/con/UserTransaction"/>

<dataSource type="JNDI">

<property name="DataSource"

value="java:comp/env/jdbc/myDataSource"/>

</dataSource>

IBATIS Developer’s Guide Version 1.0

September 2, 2004 So many open source projects. Why not Open your Documents?

</transactionManager>

⑷ sqlMap節點

sqlMap 節點指定了映射檔案的位置,配置中可出現多個sqlMap 節點,以指定

項目内所包含的所有映射檔案。