介紹
歡迎來到
iBATIS Database Layer!
這個框架將讓你能夠更好的在
Java
應用中設計和實現實體層。這個框架有兩個主要的組成部分,一個是
SQL Maps
,另一個是
Data Access Objects
。另外還包括一些可能很有用的工具。
SQL Maps
Sql Maps
是這個框架中最激動人心的部分,它是整個
iBATIS Database Layer
的核心價值所在。通過使用
Sql Maps
你可以顯著的節約數據庫操作的代碼量。
SQL Maps
使用一個簡單的
XML
文件來實現從
javaBean
到
SQL statements
的映射。跟其他的框架或者對象映射工具相比,
SQL Maps
最大的優勢是簡單。它需要學習的東西很少,在連接表或復雜查詢時也不需要復雜的
scheme(
怎么翻
complex scheme?)
,使用
SQL Maps
,
你可以自由的使用
SQL
語句。
Data Access Objects (DAO)
當我們開發靈活的
Java
應用時,有一個好主意就是通過一個通用
API
層把實體操作的細節封裝起來。
Data Access Objects
允許你通過一個簡單接口的來操作數據,從而隱藏了實現的細節。使用
DAO
,你可以動態配置你的應用程序來訪問不同的實體存儲機制。如果你有一個復雜的應用需要用到幾個不同的數據庫,
DAO
可以讓你建立一個一致的
API
,讓系統的其他部分來調用。
Utilities
iBATIS Database Layer
包含一系列的有用的工具,比如
SimpleDataSource
,
JDBC DataSource 2.0(
也包括
3.0)
的一個輕量級實現。
ScriptRunner
也提供了從單元測試到自動發布的數據庫準備工作。
Examples
跟這個框架一起有一個
examples.zip
,包含了一系列簡單的實例,在
http://www.ibatis.com
上有更多的例子,包括非常著名的
Jpestore
,
一個在線商店。
(
譯者注,藍色天空也有一系列的中文介紹和實例
)
About this Document
本文介紹了
iBATIS Database Layer
最重要的功能,還有一些功用沒有寫出來,凡是沒有寫出來的這些,可以認為是不支持或者正在修改。這些功能可能不經過通知就修改了,所以最好不要使用它們。本文將盡可能保持與框架同步。請確認你兩者是否匹配。如果有任何問題或錯誤,請發
mail
到
clinton.begin@ibatis.com
。
(
譯者注,也可以在
藍色天空
討論發帖討論
)
。
SQL Maps (com.ibatis.db.sqlmap.*)
概念
SQL Map API
允許程序員很簡單的把
Java
對象映射到
PreparedStatement
參數或者
ResultSets
。
SQL Maps
的機制很簡單,提供一個框架,來實現用
20%
的代碼來實現
80%JDBC
的功能。
How does it work?
SQL Maps
提供一個簡單的框架,通過
XML
描述來映射
JAVABeans
,
MAP implementations
甚至原始類型的包裝
(String,Integer
等
)
到
JDBC PreparedStatement
。想法很簡單,基本的步驟如下:
1)
提供一個對象作為參數
(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.).(
感覺不譯為好,你說呢?
)
2)
執行這個映射的
statement
,這一步是魔術發生的地方。
SQL Maps
框架將建立一個
PreparedStatement
實例
(instance)
,使用前面提供的對象的參數,執行
statement
,然后從
ResultSet
中建立一個返回對象。
3)
如果是
Update
,則返回有多少行修改了,如果是查詢,則返回一個對象或者對象的集合。跟參數一樣,返回對象也可以是一個
JAVABEAN
,
MAP
或者一個
primitive type wrapper
。
流程圖如下:
本篇文章的第一部分將帶你走過一系列的“
fash Track
”,帶你瀏覽一遍
SQL maps
的簡單應用。在
walkthrough
之后,將有詳細的論述。
Fast Track: Preparing to Use SQL Maps
SQL Maps
對不好的數據庫模型甚至對象模型都有很強的容忍度。盡管如此,還是推薦你使用最佳實踐來設計你的的數據庫模型和對象模型。通過這樣,你將得到更干凈的設計和更好的性能。
最簡單的開始就是分析你在做的內容,商業模型是什么樣的,表結構是什么樣的,它們怎么樣互相發生關系。第一個例子,我們就簡單的實現一個典型的
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
…
}
|
現在
persion
對象怎么映射到數據庫?
SQL Maps
并不約束你必須要一個表一個對象或者多個表一個對象這種映射關系。因為你可以自由使用
SQL
語句,所以約束很小。在這個例子里,我們使用下面簡單的表,實現一個表對象一個對象的映射關系。
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
當我們對我們的工作感到很舒適時,最好的開始就是
SQL Map
的配置文件。這個文件是
SQL Map
實現的根配置。
配置文件是
XML
文件,我們用它來配置屬性,
JDBC DataSources
和
SQL Maps
。它給我們一個便利的地方可以集中配置不同的
DataSource
。這個框架支持
iBATIS SimpleDataSource, Jakarta DBCP (Commons)
,以及其他任何可以通過
JNDI context
來訪問的
DataSource
。我們在以后將詳細討論這個問題。現在我們用
Jakarta DBCP
,結構很簡單,象上面這個例子,它的配置文件如下。
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)
現在我們已經配置好
DataSource
了,然后就要準備核心配置文件了。我們需要準備一個實際的
SQL Map
文件來存放
SQL
語句和以及用作映射的參數對象和結果對象(分別是輸入和輸出)。
繼續我們上面的示例。讓我們為
Person
類和
Person
表建立映射關系。我們先建立一個標準結構,和一個簡單的
select
說明。
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>
|
上面的示例顯示了一個
SQL map
的一個最簡單的組成。它使用了
SQL Maps
的一個特性,就是自動根據字段名和
JAVABean
屬性
(Map
的主鍵
)
名建立對應關系。
#value#
象征著一個輸入參數,多情況下,使用
"value"
意味著我們使用一個基本類型
(e.g. Integer; but we
’
re not limited to this).
因為非常簡單,所以使用這種方法有一些限制。首先不能明確指定每個字段的輸入類型。沒有辦法自動加載相關數據(復雜類型),同時有一些性能影響,因為它使用了
ResultSetMetaData
。通過使用
result-map
,我們可以克服所有這些限制。但是現在,簡單是我們的目標。同是,以后我們可以隨便修改成其他方式(不需要修改
Java
代碼)。
多數
Java
程序不僅讀取數據,還要更改數據。我們已經看到怎樣在
Map-statement
里使用
select
了,那
Update,delete
和
Insert
是什么樣的?一個好消息,跟
select
沒有什么區別。下面我們就完成一個我們的
Person Sql Map
,包括一系列的
statement
用來操作和修改數據。
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
現在我們已經完成了所有的配置和映射,剩下的就是寫
Java
代碼了。第一步是配置
SQL
Map
。加載我們前面配置好的
SQL Map XML
文件是很簡單的。加載
XML
以后,就可以在框架里使用資源類。
String resource =
“
com/ibatis/example/sql-map-config.xml
”
; Reader reader = Resources.getResourceAsReader (resource); SqlMap sqlMap = XmlSqlMapBuilder.buildSqlMap(reader);
|
SQL Map
對象是線程安全的,意味著是長期生存的。對于一個運行的系統來說,你只要配置一次。所以它可以很好的成為一個基類的靜態對象(比如,一個
BASE Dao
類),也許你更喜歡集中配置并成為全局可見,你可以把它包裝在你自己的工具類中。比如說:
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;
}
}
|
從數據庫讀取對象
現在
SQL Map
實例已經完成初始化,并且很容易訪問
,
我們可以使用它了。首先我們用它從數據庫中取得一個
Person
對象。
(
舉例,我們假設數據庫中有
10
條記錄,
PER_ID
分別從是
1
到
10)
為了從數據庫中取得一個
Person
對象,我們需要
SQL Map
實例,
mapped statement
的名稱以及
PER_ID
號
,
讓我們讀取
#5
。
…
SqlMap sqlMap = MyAppSqlMapConfig.getSqlMapInstance(); // as coded above
…
Integer personPk = new Integer(5); Person person = (Person) sqlMap.executeQueryForObject (
“
getPerson
”
, personPk);
…
|
把對象寫到數據庫中
現在我們已經從數據庫取得一個對象,讓我們修改一些值,我們將修改身高和體重。
…
person.setHeightInMeters(1.83); // person as read from the database above person.setWeightInKilograms(86.36);
…
sqlMap.executeUpdate(
“
updatePerson
”
, person);
…
|
如果我們要刪除一個對象,也一樣的簡單。
…
sqlMap.executeUpdate(
“
deletePerson
”
, person);
…
|
同樣的,新插入一個對象也類似。
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(
結束語
)
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
是一個核心的
XML
文件來配置的。這個文件包含了配置的細節和
DataSources(
數據源
),Sql Map
和其他選項,比如線程管理。以下是一個
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)
評論(0) 編輯 收藏 所屬分類:
IBATIS