posts - 431,  comments - 344,  trackbacks - 0

介绍

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

只有注册用户登录后才能发表评论。


网站导航: