介紹
歡迎來(lái)到
iBATIS Database Layer!
這個(gè)框架將讓你能夠更好的在
Java
應(yīng)用中設(shè)計(jì)和實(shí)現(xiàn)實(shí)體層。這個(gè)框架有兩個(gè)主要的組成部分,一個(gè)是
SQL Maps
,另一個(gè)是
Data Access Objects
。另外還包括一些可能很有用的工具。
SQL Maps
Sql Maps
是這個(gè)框架中最激動(dòng)人心的部分,它是整個(gè)
iBATIS Database Layer
的核心價(jià)值所在。通過(guò)使用
Sql Maps
你可以顯著的節(jié)約數(shù)據(jù)庫(kù)操作的代碼量。
SQL Maps
使用一個(gè)簡(jiǎn)單的
XML
文件來(lái)實(shí)現(xiàn)從
javaBean
到
SQL statements
的映射。跟其他的框架或者對(duì)象映射工具相比,
SQL Maps
最大的優(yōu)勢(shì)是簡(jiǎn)單。它需要學(xué)習(xí)的東西很少,在連接表或復(fù)雜查詢時(shí)也不需要復(fù)雜的
scheme(
怎么翻
complex scheme?)
,使用
SQL Maps
,
你可以自由的使用
SQL
語(yǔ)句。
Data Access Objects (DAO)
當(dāng)我們開(kāi)發(fā)靈活的
Java
應(yīng)用時(shí),有一個(gè)好主意就是通過(guò)一個(gè)通用
API
層把實(shí)體操作的細(xì)節(jié)封裝起來(lái)。
Data Access Objects
允許你通過(guò)一個(gè)簡(jiǎn)單接口的來(lái)操作數(shù)據(jù),從而隱藏了實(shí)現(xiàn)的細(xì)節(jié)。使用
DAO
,你可以動(dòng)態(tài)配置你的應(yīng)用程序來(lái)訪問(wèn)不同的實(shí)體存儲(chǔ)機(jī)制。如果你有一個(gè)復(fù)雜的應(yīng)用需要用到幾個(gè)不同的數(shù)據(jù)庫(kù),
DAO
可以讓你建立一個(gè)一致的
API
,讓系統(tǒng)的其他部分來(lái)調(diào)用。
Utilities
iBATIS Database Layer
包含一系列的有用的工具,比如
SimpleDataSource
,
JDBC DataSource 2.0(
也包括
3.0)
的一個(gè)輕量級(jí)實(shí)現(xiàn)。
ScriptRunner
也提供了從單元測(cè)試到自動(dòng)發(fā)布的數(shù)據(jù)庫(kù)準(zhǔn)備工作。
Examples
跟這個(gè)框架一起有一個(gè)
examples.zip
,包含了一系列簡(jiǎn)單的實(shí)例,在
http://www.ibatis.com
上有更多的例子,包括非常著名的
Jpestore
,
一個(gè)在線商店。
(
譯者注,藍(lán)色天空也有一系列的中文介紹和實(shí)例
)
About this Document
本文介紹了
iBATIS Database Layer
最重要的功能,還有一些功用沒(méi)有寫(xiě)出來(lái),凡是沒(méi)有寫(xiě)出來(lái)的這些,可以認(rèn)為是不支持或者正在修改。這些功能可能不經(jīng)過(guò)通知就修改了,所以最好不要使用它們。本文將盡可能保持與框架同步。請(qǐng)確認(rèn)你兩者是否匹配。如果有任何問(wèn)題或錯(cuò)誤,請(qǐng)發(fā)
mail
到
clinton.begin@ibatis.com
。
(
譯者注,也可以在
藍(lán)色天空
討論發(fā)帖討論
)
。
SQL Maps (com.ibatis.db.sqlmap.*)
概念
SQL Map API
允許程序員很簡(jiǎn)單的把
Java
對(duì)象映射到
PreparedStatement
參數(shù)或者
ResultSets
。
SQL Maps
的機(jī)制很簡(jiǎn)單,提供一個(gè)框架,來(lái)實(shí)現(xiàn)用
20%
的代碼來(lái)實(shí)現(xiàn)
80%JDBC
的功能。
How does it work?
SQL Maps
提供一個(gè)簡(jiǎn)單的框架,通過(guò)
XML
描述來(lái)映射
JAVABeans
,
MAP implementations
甚至原始類型的包裝
(String,Integer
等
)
到
JDBC PreparedStatement
。想法很簡(jiǎn)單,基本的步驟如下:
1)
提供一個(gè)對(duì)象作為參數(shù)
(either a JavaBean, Map or primitive wrapper)
,
The parameter object
will be used setting input values in an update statement, or query values in a where clause (etc.).(
感覺(jué)不譯為好,你說(shuō)呢?
)
2)
執(zhí)行這個(gè)映射的
statement
,這一步是魔術(shù)發(fā)生的地方。
SQL Maps
框架將建立一個(gè)
PreparedStatement
實(shí)例
(instance)
,使用前面提供的對(duì)象的參數(shù),執(zhí)行
statement
,然后從
ResultSet
中建立一個(gè)返回對(duì)象。
3)
如果是
Update
,則返回有多少行修改了,如果是查詢,則返回一個(gè)對(duì)象或者對(duì)象的集合。跟參數(shù)一樣,返回對(duì)象也可以是一個(gè)
JAVABEAN
,
MAP
或者一個(gè)
primitive type wrapper
。
流程圖如下:
本篇文章的第一部分將帶你走過(guò)一系列的“
fash Track
”,帶你瀏覽一遍
SQL maps
的簡(jiǎn)單應(yīng)用。在
walkthrough
之后,將有詳細(xì)的論述。
Fast Track: Preparing to Use SQL Maps
SQL Maps
對(duì)不好的數(shù)據(jù)庫(kù)模型甚至對(duì)象模型都有很強(qiáng)的容忍度。盡管如此,還是推薦你使用最佳實(shí)踐來(lái)設(shè)計(jì)你的的數(shù)據(jù)庫(kù)模型和對(duì)象模型。通過(guò)這樣,你將得到更干凈的設(shè)計(jì)和更好的性能。
最簡(jiǎn)單的開(kāi)始就是分析你在做的內(nèi)容,商業(yè)模型是什么樣的,表結(jié)構(gòu)是什么樣的,它們?cè)趺礃踊ハ喟l(fā)生關(guān)系。第一個(gè)例子,我們就簡(jiǎn)單的實(shí)現(xiàn)一個(gè)典型的
Persion
類。
Person.java package examples.domain; //imports implied
…
. public class Person { private int id; private String firstName; private String lastName; private Date birthDate; private double weightInKilograms; private double heightInMeters; public int getId () { return id; } public void setId (int id) { this.id = id; } //
…
let
’
s assume we have the other getters and setters to save space
…
}
|
現(xiàn)在
persion
對(duì)象怎么映射到數(shù)據(jù)庫(kù)?
SQL Maps
并不約束你必須要一個(gè)表一個(gè)對(duì)象或者多個(gè)表一個(gè)對(duì)象這種映射關(guān)系。因?yàn)槟憧梢宰杂墒褂?/span>
SQL
語(yǔ)句,所以約束很小。在這個(gè)例子里,我們使用下面簡(jiǎn)單的表,實(shí)現(xiàn)一個(gè)表對(duì)象一個(gè)對(duì)象的映射關(guān)系。
Person.sql CREATE TABLE PERSON( PER_ID NUMBER (5, 0) NOT NULL, PER_FIRST_NAME VARCHAR (40) NOT NULL, PER_LAST_NAME VARCHAR (40) NOT NULL, PER_BIRTH_DATE DATETIME , PER_WEIGHT_KG NUMBER (4, 2) NOT NULL, PER_HEIGHT_M NUMBER (4, 2) NOT NULL, PRIMARY KEY (PER_ID) )
|
Fast Track: The SQL Map Configuration File
當(dāng)我們對(duì)我們的工作感到很舒適時(shí),最好的開(kāi)始就是
SQL Map
的配置文件。這個(gè)文件是
SQL Map
實(shí)現(xiàn)的根配置。
配置文件是
XML
文件,我們用它來(lái)配置屬性,
JDBC DataSources
和
SQL Maps
。它給我們一個(gè)便利的地方可以集中配置不同的
DataSource
。這個(gè)框架支持
iBATIS SimpleDataSource, Jakarta DBCP (Commons)
,以及其他任何可以通過(guò)
JNDI context
來(lái)訪問(wèn)的
DataSource
。我們?cè)谝院髮⒃敿?xì)討論這個(gè)問(wèn)題?,F(xiàn)在我們用
Jakarta DBCP
,結(jié)構(gòu)很簡(jiǎn)單,象上面這個(gè)例子,它的配置文件如下。
SqlMapConfigExample.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sql-map-config PUBLIC "-//iBATIS.com//DTD SQL Map Config 1.0//EN" "http://www.ibatis.com/dtd/sql-map-config.dtd">
<!-- Always ensure to use the correct XML header as above! -->
<sql-map-config>
<!-- The properties (name=value) in the file specified here can be used placeholders in this config file (e.g.
“
${driver}
”
. The file is relative to the classpath and is completely optional. -->
<properties resource="examples/sqlmap/maps/SqlMapConfigExample.properties" />
<!-- These settings control SqlMap configuration details, primarily to do with transaction management. They are all optional (more detail later in this document). -->
<settings maxExecute="300" maxExecutePerConnection="1" maxTransactions="10" statementCacheSize="75" useGlobalTransactions="false" useBeansMetaClasses=
”
true
”
/> <!-- Configure a datasource to use with this SQL Map using Jakarta DBCP. Notice the use of the properties from the above resource --> <datasource name="basic" default = "true" factory-class="com.ibatis.db.sqlmap.datasource.DbcpDataSourceFactory"> <property name="JDBC.Driver" value="${driver}"/> <property name="JDBC.ConnectionURL" value="${url}"/> <property name="JDBC.Username" value="${username}"/> <property name="JDBC.Password" value="${password}"/> <property name="Pool.MaximumActiveConnections" value="10"/> <property name="Pool.MaximumIdleConnections" value="5"/> <property name="Pool.MaximumWait" value="60000"/> </datasource>
<!-- Identify all SQL Map XML files to be loaded by this SQL map. Notice the paths are relative to the classpath. For now, we only have one
…
-->
<sql-map resource="examples/sqlmap/maps/Person.xml" />
</sql-map-config>
|
SqlMapConfigExample.properties
# This is just a simple properties file that simplifies automated configuration # of the SQL Maps configuration file (e.g. by Ant builds or continuous # integration tools for different environments
…
etc.) # These values can be used in any property value in the file above (e.g.
“
${driver}
”
) # Using a properties file such as this is completely optional.
driver=oracle.jdbc.driver.OracleDriver url=jdbc:oracle:thin:@localhost:1521:oracle1 username=jsmith password=test
|
Fast Track: The SQL Map File(s)
現(xiàn)在我們已經(jīng)配置好
DataSource
了,然后就要準(zhǔn)備核心配置文件了。我們需要準(zhǔn)備一個(gè)實(shí)際的
SQL Map
文件來(lái)存放
SQL
語(yǔ)句和以及用作映射的參數(shù)對(duì)象和結(jié)果對(duì)象(分別是輸入和輸出)。
繼續(xù)我們上面的示例。讓我們?yōu)?/span>
Person
類和
Person
表建立映射關(guān)系。我們先建立一個(gè)標(biāo)準(zhǔn)結(jié)構(gòu),和一個(gè)簡(jiǎn)單的
select
說(shuō)明。
Person.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sql-map PUBLIC "-//iBATIS.com//DTD SQL Map 1.0//EN" "http://www.ibatis.com/dtd/sql-map.dtd">
<sql-map name="Person">
<mapped-statement name="getPerson" result-class="examples.domain.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# </mapped-statement> </sql-map>
|
上面的示例顯示了一個(gè)
SQL map
的一個(gè)最簡(jiǎn)單的組成。它使用了
SQL Maps
的一個(gè)特性,就是自動(dòng)根據(jù)字段名和
JAVABean
屬性
(Map
的主鍵
)
名建立對(duì)應(yīng)關(guān)系。
#value#
象征著一個(gè)輸入?yún)?shù),多情況下,使用
"value"
意味著我們使用一個(gè)基本類型
(e.g. Integer; but we
’
re not limited to this).
因?yàn)榉浅:?jiǎn)單,所以使用這種方法有一些限制。首先不能明確指定每個(gè)字段的輸入類型。沒(méi)有辦法自動(dòng)加載相關(guān)數(shù)據(jù)(復(fù)雜類型),同時(shí)有一些性能影響,因?yàn)樗褂昧?/span>
ResultSetMetaData
。通過(guò)使用
result-map
,我們可以克服所有這些限制。但是現(xiàn)在,簡(jiǎn)單是我們的目標(biāo)。同是,以后我們可以隨便修改成其他方式(不需要修改
Java
代碼)。
多數(shù)
Java
程序不僅讀取數(shù)據(jù),還要更改數(shù)據(jù)。我們已經(jīng)看到怎樣在
Map-statement
里使用
select
了,那
Update,delete
和
Insert
是什么樣的?一個(gè)好消息,跟
select
沒(méi)有什么區(qū)別。下面我們就完成一個(gè)我們的
Person Sql Map
,包括一系列的
statement
用來(lái)操作和修改數(shù)據(jù)。
Person.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sql-map
PUBLIC "-//iBATIS.com//DTD SQL Map 1.0//EN"
"http://www.ibatis.com/dtd/sql-map.dtd">
<sql-map name="Person">
<!-- Use primitive wrapper type (e.g. Integer) as parameter and allow results to
be auto-mapped results to Person object (JavaBean) properties -->
<mapped-statement name="getPerson" result-class="examples.domain.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#
</mapped-statement>
<!-- Use Person object (JavaBean) properties as parameters for insert. Each of the
parameters in the #hash# symbols is a JavaBeans property. -->
<mapped-statement name="insertPerson" >
INSERT INTO
PERSON (PER_ID, PER_FIRST_NAME, PER_LAST_NAME,
PER_BIRTH_DATE, PER_WEIGHT_KG, PER_HEIGHT_M)
VALUES (#id#, #firstName#, #lastName#,
#birthDate#, #weightInKilograms#, #heightInMeters#)
</mapped-statement>
<!-- Use Person object (JavaBean) properties as parameters for update. Each of the
parameters in the #hash# symbols is a JavaBeans property. -->
<mapped-statement name="updatePerson" >
UPDATE PERSON
SET (PER_ID = PER_FIRST_NAME = #firstName#,
PER_LAST_NAME = #lastName#, PER_BIRTH_DATE = #birthDate#,
PER_WEIGHT_KG = #weightInKilograms#,
PER_HEIGHT_M = #heightInMeters#)
WHERE PER_ID = #id#
</mapped-statement>
<!-- Use Person object (JavaBean) “id” properties as parameters for delete. Each of the
parameters in the #hash# symbols is a JavaBeans property. -->
<mapped-statement name="deletePerson" >
DELETE PERSON
WHERE PER_ID = #id#
</mapped-statement>
</sql-map>
|
Fast Track: Programming with the SQL Map Framework
現(xiàn)在我們已經(jīng)完成了所有的配置和映射,剩下的就是寫(xiě)
Java
代碼了。第一步是配置
SQL
Map
。加載我們前面配置好的
SQL Map XML
文件是很簡(jiǎn)單的。加載
XML
以后,就可以在框架里使用資源類。
String resource =
“
com/ibatis/example/sql-map-config.xml
”
; Reader reader = Resources.getResourceAsReader (resource); SqlMap sqlMap = XmlSqlMapBuilder.buildSqlMap(reader);
|
SQL Map
對(duì)象是線程安全的,意味著是長(zhǎng)期生存的。對(duì)于一個(gè)運(yùn)行的系統(tǒng)來(lái)說(shuō),你只要配置一次。所以它可以很好的成為一個(gè)基類的靜態(tài)對(duì)象(比如,一個(gè)
BASE Dao
類),也許你更喜歡集中配置并成為全局可見(jiàn),你可以把它包裝在你自己的工具類中。比如說(shuō):
private
MyAppSqlConfig {
private
static final SqlMapsqlMap;
static
{
try
{
String resource = “com/ibatis/example/sql-map-config.xml”;
Reader reader = Resources.getResourceAsReader (resource);
sqlMap
= XmlSqlMapBuilder.buildSqlMap(reader);
} catch (Exception e) {
// If you get an error at this point, it matters little what it was. It is going to be
// unrecoverable and we will want the app to blow up good so we are aware of the
// problem. You should always log such errors and re-throw them in such a way that
// you can be made immediately aware of the problem.
e.printStackTrace(
);
throw
new RuntimeException (“Error initializing MyAppSqlConfig class. Cause: ” + e);
}
}
public
static getSqlMapInstance () {
return
sqlMap;
}
}
|
從數(shù)據(jù)庫(kù)讀取對(duì)象
現(xiàn)在
SQL Map
實(shí)例已經(jīng)完成初始化,并且很容易訪問(wèn)
,
我們可以使用它了。首先我們用它從數(shù)據(jù)庫(kù)中取得一個(gè)
Person
對(duì)象。
(
舉例,我們假設(shè)數(shù)據(jù)庫(kù)中有
10
條記錄,
PER_ID
分別從是
1
到
10)
為了從數(shù)據(jù)庫(kù)中取得一個(gè)
Person
對(duì)象,我們需要
SQL Map
實(shí)例,
mapped statement
的名稱以及
PER_ID
號(hào)
,
讓我們讀取
#5
?!?/span>
…
SqlMap sqlMap = MyAppSqlMapConfig.getSqlMapInstance(); // as coded above
…
Integer personPk = new Integer(5); Person person = (Person) sqlMap.executeQueryForObject (
“
getPerson
”
, personPk);
…
|
把對(duì)象寫(xiě)到數(shù)據(jù)庫(kù)中
現(xiàn)在我們已經(jīng)從數(shù)據(jù)庫(kù)取得一個(gè)對(duì)象,讓我們修改一些值,我們將修改身高和體重。
…
person.setHeightInMeters(1.83); // person as read from the database above person.setWeightInKilograms(86.36);
…
sqlMap.executeUpdate(
“
updatePerson
”
, person);
…
|
如果我們要?jiǎng)h除一個(gè)對(duì)象,也一樣的簡(jiǎn)單。
…
sqlMap.executeUpdate(
“
deletePerson
”
, person);
…
|
同樣的,新插入一個(gè)對(duì)象也類似。
Person newPerson = new Person(); newPerson.setId(11); // you would normally get the ID from a sequence or custom table newPerson.setFirstName(
“
Clinton
”
); newPerson.setLastName(
“
Begin
”
); newPerson.setBirthDate (null); newPerson.setHeightInMeters(1.83); newPerson.setWeightInKilograms(86.36);
…
sqlMap.executeUpdate (
“
insertPerson
”
, newPerson);
…
|
End of Fast Track(
結(jié)束語(yǔ)
)
This is the end of the quick walkthrough. The next several sections will discuss the features of the
SqlMap framework in more detail.
The SQL Map XML Configuration File
(http://www.ibatis.com/dtd/sql-map-config.dtd)
SQL Map
是一個(gè)核心的
XML
文件來(lái)配置的。這個(gè)文件包含了配置的細(xì)節(jié)和
DataSources(
數(shù)據(jù)源
),Sql Map
和其他選項(xiàng),比如線程管理。以下是一個(gè)
SqlMap
的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sql-map-config PUBLIC "-//iBATIS.com//DTD SQL Map Config 1.0//EN"
"http://www.ibatis.com/dtd/sql-map-config.dtd">
<!-- Always ensure to use the correct XML header as above! -->
<sql-map-config>
<!-- The properties (name=value) in the file specified here can be used placeholders in this config
file (e.g. "${driver}". The file is relative to the classpath and is completely optional. -->
<properties resource="examples/sqlmap/maps/SqlMapConfigExample.properties" />
<!-- These settings control SqlMap configuration details, primarily to do with transaction
management. They are all optional (more detail later in this document). -->
<settings maxExecute="300"
maxExecutePerConnection="1"
maxTransactions="10"
statementCacheSize="75"
useGlobalTransactions="false"
useBeansMetaClasses="true" />
<!-- Configure a datasource to use with this SQL Map using Jakarta DBCP
notice the use of the properties from the above resource -->
<datasource name="basic" default = "true"
factory-class="com.ibatis.db.sqlmap.datasource.DbcpDataSourceFactory">
<property name="JDBC.Driver" value="${driver}"/>
<property name="JDBC.ConnectionURL" value="${url}"/>
<property name="JDBC.Username" value="${username}"/>
<property name="JDBC.Password" value="${password}"/>
<property name="Pool.MaximumActiveConnections" value="10"/>
<property name="Pool.MaximumIdleConnections" value="5"/>
<property name="Pool.MaximumWait" value="60000"/>
</datasource>
<!-- Identify all SQL Map XML files to be loaded by this SQL map. Notice the paths
are relative to the classpath. -->
<sql-map resource="examples/sqlmap/maps/Person.xml" />
<sql-map resource="examples/sqlmap/maps/Account.xml" />
<sql-map resource="examples/sqlmap/maps/Order.xml" />
<sql-map resource="examples/sqlmap/maps/LineItem.xml" />
<sql-map resource="examples/sqlmap/maps/Product.xml" />
</sql-map-config>
|
posted on 2006-09-06 16:46
周銳 閱讀(585)
評(píng)論(0) 編輯 收藏 所屬分類:
IBATIS