介绍
欢迎来到
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
周锐 阅读(575)
评论(0) 编辑 收藏 所属分类:
IBATIS