现在来简短的介绍一下笔者用过的一些持久化框架和技术,之所以前面强调那么多共通的知识,是希望大家不要盲从流行框架,一定要把握它的本质和卓越的思想好在哪里。
1. Apache OJB
OJB代表Apache Object Relational Bridge,是Apache开发的一个数据库持久型框架。它是基于J2ee规范指南下的持久型框架技术而设计开发的,例如实现了ODMG 3.0规范的API,实现了JDO规范的API, 核心实现是Persistence Broker API。OJB使用XML文件来实现映射并动态的在Metadata layer听过一个Meta-Object-Protocol(MOP)来改变底层数据的行为。更高级的特点包括对象缓存机制、锁管理机制、 Virtual 代理、事务隔离性级别等等。举个OJB Mapping的简单例子ojb-repository.xml:
<class-descriptor class=”com.ant.Employee” table=”EMPLOYEE”>
<field-descriptor name=”id” column=”ID”
jdbc-type=”INTEGER” primarykey=”true” autoincrement=”true”/>
<field-descriptor name=”name” column=”NAME” jdbc-type=”VARCHAR”/>
</class-descrptor>
<class-descriptor class=”com.ant.Executive” table=”EXECUTIVE”>
<field-descriptor name=”id” column=”ID”
jdbc-type=”INTEGER” primarykey=”true” autoincrement=”true”/>
<field-descriptor name=”department” column=”DEPARTMENT” jdbc-type=”VARCHAR”/>
<reference-descriptor name=”super” class-ref=”com.ant.Employee”>
<foreignkey field-ref=”id”/>
</reference-descriptor>
</class-descrptor>
2. iBATIS
iBATIS最大的特点就是允许用户自己定义SQL来组配Bean的属性。因为它的SQL语句是直接写入XML文件中去的,所以可以最大程度上利用到 SQL语法本身能控制的全部特性,同时也能允许你使用特定数据库服务器的额外特性,并不局限于类似SQL92这样的标准,它最大的缺点是不支持枚举类型的 持久化,即把枚举类型的几个对象属性拼成与数据库一个字段例如VARCHAR对应的行为。这里也举一个Mapping文件的例子sqlMap.xml:
<sqlMap>
<typeAlias type=”com.ant.Test” alias=”test”/>
<resultMap class=”test” id=”result”>
<result property=”testId” column=”TestId”/>
<result property=”name” column=”Name”/>
<result property=”date” column=”Date”/>
</resultMap>
<select id=”getTestById” resultMap=”result” parameterClass=”int”>
select * from Test where TestId=#value#
</select>
<update id=”updateTest” parameterClass=”test”>
Update Tests set Name=#name#, Date=”date” where TestId=#testId#
</update>
</sqlMap>
3. Hibernate
Hibernate无疑是应用最广泛最受欢迎的持久型框架,它生成的SQL语句是非常优秀。虽然一度因为不能支持手工SQL而性能受到局限,但随着新一代 Hibernate 3.x推出,很多缺点都被改进,Hibernate也因此变得更加通用而时尚。同样先看一个Mapping文件的例子customer.hbm.xml来 有一个大概印象:
<hibernate-mapping>
<class name=”com.ant.Customer” table=”Customers”>
<id name=”customerId” column=”CustomerId” type=”int” unsaved-value=”0”>
<generator class=”sequence”>
<param name=”sequence”> Customers_CustomerId_Seq </param>
</generator>
</id>
<property name=”firstName” column=”FirstName”/>
<property name=”lastName” column=”LastName”/>
<set name=”addresses” outer-join=”true”>
<key column=”Customer”/>
<one-to-many class=”com.ant.Address”/>
</set>
</class>
</hibernate-mapping>
Hibernate有很多显著的特性,最突出的就是它有自己的查询语言叫做HQL,在HQL中select from的不是Table而是类名,一方面更加面向对象,另外一方面通过在hibernate.cfg.xml中配置Dialect为HQL可以使得整个 后台与数据库脱离耦合,因为不管用那种数据库我都是基于HQL来查询,Hibernate框架负责帮我最终转换成特定数据库里的SQL语句。另外 Hibernate在Object-Caching这方面也做得相当出色,它同时管理两个级别的缓存,当数据被第一次取出后,真正使用的时候对象被放在一 级缓存管理,这个时候任何改动都会影响到数据库;而空闲时候会把对象放在二级缓存管理,虽然这个时候与数据库字段能对应上但未绑定在一起,改动不会影响到 数据库的记录,主要目的是为了在重复读取的时候更快的拿到数据而不用再次请求连接对象。其实关于这种缓存的设计建议大家研究一下Oracle的存储机制 (原理是相通的),Oracle牺牲了空间换来时间依赖于很健壮的缓存算法来保证最优的企业级数据库访问速率。
以上是一些Mapping的例子,真正在Java代码中使用多半是继承各个框架中默认的Dao实现类,然后可以通过Id来查找对象,或者通过 Example来查找,更流行的是更具Criteria查找对象。Criteria是完全封装了SQL条件查询语法的一个工具类,任何一个查询条件都可以 在Criteria中找到方法与之对应,这样可以在Java代码级别实现SQL的完全控制。另外,现在许多ORM框架的最新版本随着JDk 5.0加入Annotation特性都开始支持用XDoclet来自动根据Annotation来生成XML配置文件了。
笔者不可能详细的讲解每一个框架,也许更多的人在用Hibernate,笔者是从OJB开始接触ORM技术的,它很原始却更容易让人理解从JDBC到 ORM的过渡。更多的细节是可以从官方文档和书籍中学到的,但我们应该更加看中它们设计思想的来源和闪光点,不是盲从它们的使用方法。