内容:
相关内容:
比较 Java 数据对象和 EJB 技术
级别:中级
Kyle Gabhart(kyle@gabhart.com)
--顾问,Gabhart Consulting
2003 年 7 月
上月的“探险者”专栏介绍了用于数据持久性的 J2EE 技术:实体 bean、JDBC 和 Java 数据对象(Java Data Object,JDO)。本月,企业 Java 专家 Kyle Gabhart 不再专门讨论比较成熟的 JDBC 技术和 EJB 技术,而是主要介绍 JDO。尽管这种技术与其它技术相比还不成熟,但您会发现 JDO 有一些独一无二的优点。应用程序组件应实现针对企业服务的请求。要实现这些请求,应用程序组件常常必须更改底层数据存储的状态。这些更改绝对不能破坏持久数据存储的完整性。(在有关数据持久性的第一篇文章中,我们将持久数据存储定义为独立的数据资源库,即使在服务器崩溃或网络失败时,这个数据资源库也能保护其中的数据。)为了确保持久性,应用程序组件必须能处理并发性、连接管理、数据完整性以及同步。J2EE 的三种数据管理技术都能为开发人员处理这些功能,只不过每种技术都有自己的处理方法。
上月我们探讨了实体 bean 和 JDBC 的优缺点。本月,我们将查看 Java 数据对象如何与无状态会话 bean 组合,以及该解决方案如何与标准实体 bean 应用程序进行比较。由于 JDO 仍是一种相当新的技术(最新的 J2EE 持久性解决方案),所以我们将首先概述其工作原理。
JDO 概述
长久以来,Java 应用程序和持久数据管理之间的关系一直是不容易处理的。许多持久性机制以关系的方法而不是面向对象方法存储数据。即,数据存储在由包含字段的记录组成的表中,而不是存储为自包含对象(这些对象拥有内部数据和对其它对象的引用,而其它对象也拥有内部数据和引用)。将面向对象的表示转换成关系表示一直就很麻烦、易出错且会降低应用程序性能。直到最近,少数几个本质上是非关系型的持久性机制(例如 SQL BLOB 和 Java 序列化)使用起来也很麻烦。大多数持久性机制让开发人员负责处理持久性,或使用非 Java 语言(例如 SQL)与后端数据存储进行相互作用。
JDO 的优点在于它很简单。开发人员使用 Java 语言持久存储对象实例并从存储器检索实例。处理逻辑、同步和故障转移等均被透明地处理。开发人员无需使用 SQL 或 Java 语言提供的不便的序列化机制,只使用 POJO(无格式普通 Java 对象)即可,利用 JDO 接口将对象引用传递到存储器中并从存储器检索对象引用。
J2EE 持久性技术
实体 bean 提供健壮的数据持久性。bean 容器处理数据完整性、资源管理和并发性功能的绝大部分工作,从而让开发人员专注于业务逻辑和数据处理,而不必考虑这些低级别的细节。使用 Bean 管理的持久性(Bean Managed Persistence,BMP)实体 bean,开发人员编写持久性代码,但由容器确定何时执行该代码。使用容器管理的持久性(Container Managed Persistence,CMP)实体 bean,容器生成持久性代码,并管理持久性逻辑。
JDBC 在与会话 bean 组合时可以提供容易的 EJB 开发以及与平台无关的部署,并且没有 EJB 技术中常见的资源使用和内存开销。与 BMP 实体 bean 类似,这一解决方案要求开发人员编写持久性代码。与 BMP bean 不同的是,它还要求开发人员编写持久性逻辑。因此,开发人员就要负责确定何时使数据持久保存到数据存储以及何时从数据存储装入数据。
Java 数据对象(JDO)是最新的持久性机制。JDO 提供了面向对象的持久数据存储。开发人员可以使用 POJO(无格式普通 Java 对象)来装入和存储持久数据。
JDO 还采用了很多 JDBC 使用的高级体系结构。它使用一种可插入的体系结构,在这一体系结构中,开发人员将自己的代码编写成标准接口集(JDO API),而供应商提供这些接口的实现。这允许使用 JDO 接口的应用程序“插入”任何支持 JDO API 的数据存储。和 JDBC 一样,这可以使移植容易,并促进各供应商之间的竞争,从而产生更好的产品,因为供应商会力争提供更有效且功能更强大的实现。
会话 bean 和 JDO
会话 bean 是任何合并了 EJB 技术的 J2EE 体系结构的基干。对于无状态会话 bean 尤其如此。正如以前讨论的,无状态会话 bean 的稳定性和可预测性使其特别适合于管理持久的企业数据。
但是会话 bean 本身不能访问持久数据存储。它们必须与其它技术(如实体 bean、JDBC 或 JDO)相结合以创建一种持久数据管理机制。将会话 bean 与 JDO 结合类似于将它们与 JDBC 结合,但 JDO 是以更面向对象且更以 Java 为中心的观点处理该问题的。
功能强大的组合
通过向 EJB 容器请求资源管理器连接工厂,企业 bean 获得对外部资源的访问权。使用 JDBC 的 EJB 组件是这样做的,使用 JDO 的 EJB 组件也是这样做的。会话 bean 必须做的第一件事是通过调用 JNDI 查询,获得对 PersistenceManagerFactory 的引用。然后从工厂获得 PersistenceManager 实例。如果会话 bean 正在使用容器管理的事务,那么每个业务方法将使用工厂来获得新的 PersistenceManager 实例,之后在退出该方法之前关闭该实例。如果使用的是 bean 管理的事务,那么开发人员将确定事务的开始条件和结束条件。因此,可以在多个业务方法调用中使用同一 PersistenceManager 实例。同样,可以在一个业务方法中打开并管理多个事务。PersistenceManager API 支持所有这些方案。
与 PersistenceManager 交互的 JDO API 很简单且非常直观。开发人员通过调用 makePersistent() 方法使对象持久。而且,这个方法特征符被重载,从而允许将各种对象类型视为持久对象(单个对象、对象数组或对象集合)。检索对象同样很简单。getObjectById() 方法使用由开发人员确定的唯一值(类似于主键)来区别对象实例。JDO 还支持基于类型的查询,这些查询能基于指定的类型(即,实现公共接口的子类和类)检索单个对象或对象集合。与 JDBC 类似,JDO 支持基本的事务性控件:begin()、commit() 和 rollback(),并能指出 PersistenceManager 实例应该采用乐观的还是悲观的事务管理方法。
优点
作为组合技术解决方案,会话 bean 和 JDO 提供了许多优点,其中有些来自会话 bean,而其它的来自 JDO。正如我们上个月所了解的,使用会话 bean 而不使用实体 bean 进行交付的主要优点有两个:
设计简单。从体系结构设计的观点来看,直接通过会话 bean 来处理数据管理比使用实体 bean 简单得多。
细粒度控制。因为会话 bean 是通用的工作程序组件,所以它们允许开发人员对整个持久性进程进行完全控制,包括高速缓存、持久性、并发性和同步等。
这两个优点并不是会话 bean/JDO 组合所特有的:会话 bean 与 JDBC 的结对也存在这两个优点。但是,JDO 确实提供了一些独特的优点:
编码简单。JDO 体系结构向开发人员隐藏了低级别的持久性细节,从而使他们专注于从业务过程的角度管理对象,不至于陷入数据持久性逻辑的琐碎细节中。
提高的生产力。JDO 程序员能完全在面向对象的范例内操作。这通常会使开发更简洁、更平滑且更不易出错,因为程序员不用在关系的思想体系和面向对象的思想体系之间频繁地转换。
面向对象的持久性。JDO 的面向对象本质不仅提高了开发人员生产力,而且它还考虑到比关系持久性所提供的还要丰富的持久性机制。JDO 并不仅仅使 Java 对象持久;它还透明地处理整个相关对象图的持久性。因此,当实例被持久存储时,它所维护的对其它对象实例的任何内部引用也都被持久存储(除非它们已被声明为瞬态)。JDO 还存储类型层次结构的完整信息,并能根据类型(父类和接口)实现请求,而不是只了解持久实例的特定局部类型。
概括起来,将会话 bean 与 JDO 结合使用可以产生三个主要优点:简单(在设计和开发方面)、生产力以及增强了对数据持久性的控制。
缺点
从其优点来看,会话 bean 与 JDO 是完美的组合,可以解决所有持久性难题!但还是让我们考虑一下这种方法的一些缺点:
JDO 不成熟。JDO 还处于初期。到编写本文时,JDO 1.0 规范的发布还不到一年。其结果是,JDO 社区还非常小,最大且最具威望的 JDO 门户网站可以炫耀的也只是其会员有五千多一点。尽管这些数据并不表示 JDO 是一种差劲的技术,但它们确实表明它还处于前沿。几乎没有几家公司愿意尝试在业务级实现中使用 JDO。所有这些现状使 JDO 开发人员和架构设计师几乎没有已经实践证明的设计模式或案例研究来指导他们的 JDO 开发工作。
会话 bean 不是事务性的。J2EE 客户机不能直接访问 JDO 对象。必须由 servlet 或会话 bean 处理进入请求。因此,尽管很容易将 JDO 对象声明为事务性的,但仍必须使用非事务性组件来访问它们。在将事务语义直接编码到会话 bean 的应用程序代码中时,开发人员必须尽一切可能确保每个功能的业务规则、流程控制和事务完整性都得以保留并是容错的。尽管使用容器管理的事务可以极大地缓解这一问题,但是这样做限制了开发人员对持久性进程的控制,并除去了许多控制事务粒度所产生的体系结构上的灵活性。
概括起来,会话 bean 和 JDO 的组合有两个主要缺点:与别的技术相比,JDO 是一种未经实践证明的技术,而会话 bean 向业务过程引入了固有的非事务层。
实体 bean
我们已(在前一篇文章中)较详细地讨论了使用实体 bean 的优缺点,所以这里只概括与本文关系最紧密的几点。
作为企业数据持久性机制,实体 bean 有五个主要优点:
标准化。EJB 规范比较成熟,因而有许多优势:众所周知的设计模式、案例研究和最佳实践,还有丰富的供应商支持的开发工具集。
容器管理的服务。EJB 容器使开发人员不必管理常见的企业功能,如安全性、事务处理、连接合用和外部资源管理。
透明的持久性。实体 bean 为处理持久性提供了两个透明选项。容器管理的持久性(CMP)实体 bean 在容器中自动处理所有持久性语义。bean 管理的持久性(BMP)实体 bean 允许开发人员编写持久性逻辑,但仍然减轻了确保数据完整性和并发性的责任(通过将这些任务分配给容器)。
事务支持。实体 bean 提供了两个事务支持模型。在 CMP bean 中声明事务语义。在 BMP bean 中,开发人员直接实现这些语义。这两种情况中,都是容器管理事务,并确定应该提交给定的事务还是应该回滚它。
基于组件的设计。实体 bean 被设计成自我包含的组件,这些组件使用部署描述符配置,并且不用修改任何代码就可以将它们部署到任何 J2EE 应用程序服务器中。
另一方面,实体 bean 也有四个主要缺点:
设计复杂性。容器管理的服务和自动且透明的持久性为整个应用程序设计引入了复杂性。实体 bean 通常也可以通过会话 bean 来访问,这意味着每个事务至少包含两个企业 bean,而通常会更多。
构建周期很长。一个 EJB 周期(设计/构建/测试/集成/测试/部署)所花的时间比可比的 Java 持久性解决方案多两到三倍。
响应时间。实体 bean 与 bean 实例的粒度相关。因此,开发人员始终面临选择:要么将 bean 按原样装入,而在别的方面解决响应时间长的问题;要么将数据分解成较小的实体,从而创建更复杂的系统体系结构。
资源使用情况。实体 bean 消耗了大量系统资源。
概括起来,实体 bean 得益于标准化和业界最佳实践、减少了企业开发的一些复杂性并提供了牢固的基于组件的设计。但获得这些优点所付出的代价就是实体 bean 通常会引入复杂性和很长的构建周期,从而使包含它们的系统设计和开发更困难。实体 bean 还由于过度消耗资源以及对大型实体并发请求的响应较慢而声誉欠佳。
几点对比
在比较任何两种技术时,重要的是不仅要考虑它们的差别,还要考虑它们的相似点。作为 J2EE 技术,实体 bean 和 Java 数据对象有几个共同的特性。我们先讨论这几个特性,随后讨论每种解决方案特有的优缺点。
实体 bean 和 JDO 都有以下特征:
透明的持久性。透明的持久性所带来的自由是人们梦寐以求的,开发人员不必知道也不必关心其中的技术持久性细节。JDO 和实体 bean 都使 Java 程序员享受到了这一点。
可移植性。JDO 和实体 bean 都基于与供应商无关的标准。使用各自的标准 API 编写的应用程序可以移植到不同供应商的 API 实现。
灵活的事务管理。JDO 和实体 bean 都为开发人员提供了选择:通过编程管理事务,还是自动管理事务。JDO 使用 PersistenceManager 管理事务,而实体 bean 将事务管理委派给了 EJB 容器。
在确定采用实体 bean 还是采用 JDO 时,请考虑这两种技术的以下优缺点:
最佳实践与设计复杂性。Enterprise JavaBeans 技术包含丰富的文献、已成文的设计模式和最佳实践、精巧的工具以及大量拥有 EJB 技术经验的 J2EE 程序员。其缺点是,实体 bean 的复杂性使您必须运用所有这些有用资产才能确保项目成功。针对大量的 EJB 技术,架构设计师和开发人员必须在有经验的程序员、设计模式和业界最佳实践的可用性方面找到平衡。
缺乏经验与简单性。对于在最佳实践方面的不足,JDO 用简单性来弥补。它很简单且易使用,而且 POJO 比“实体”概念更易于理解。尽管拥有实际 JDO 经验的 Java 编程专家很少,但该技术很容易掌握。相对于 JDO 固有的简单性,J2EE 架构设计师和开发人员必须权衡缺乏模式、最佳实践和案例研究所产生的影响。
缺乏旧的支持。目前,没有任何主要的关系数据库管理系统(RDBMS)供应商支持 JDO。因此,开发人员必须将系统数据迁移到支持 JDO 的供应商,或者将 JDO 只用于其功能不依赖旧 RDBMS 数据存储的新项目或组件。
新的持久性范例。JDO 考虑到了丰富的面向对象的持久性机制,它充分利用了对象合成(包含其它对象的对象)及继承(通过完整的类型层次结构来识别对象类型)。尽管 JDO 的面向对象持久性范例给应用程序开发人员带来了许多便利,但它也使数据库管理员(DBA)灰心和困惑。目前 JDO 不提供结合存储过程的机制,因此 DBA 要花大力气学习如何使用 XML 声明约束,或如何指导 Java 开发人员怎样管理数据。我们再次发现 JDO 更适合于新项目、新组件或现有的独立于旧 RDBMS 的应用程序。
资源使用情况。尽管可用的性能基准测试程序非常少,但我们可以假设依赖实体 bean 而获得透明持久性的应用程序所消耗的服务器资源将比基于 JDO 的应用程序多。
结束语
在这篇 J2EE 探险者系列的专栏文章中,我们已经完成了对数据持久性的探究,它是 Java 开发中最具有技巧性的领域之一。尽管 J2EE 对处理数据持久性确实提供了三种可靠技术,但没有一种是完美的。
多年来 JDBC 一直是 Java 开发人员进行数据访问的标准。它是一种牢固的且已证实的技术,允许架构设计师和开发人员利用现有关系数据库基础结构和现有的专门技术来产生数据库查询。随着时间的流逝,它已经发展成可以提供完全具有高速缓存和资源池机制的完善的数据库驱动程序,很显然这使开发人员得益颇多。作为企业持久性技术,JDBC 还存在一些不足,它让开发人员或数据库负责管理并发性和数据完整性。尽管有这个缺点,但是由于其成熟性、普遍适用性和性能使它被广泛使用。
实体 bean 比 JDBC 稍欠成熟,但是它们仍对企业数据持久性提供了可靠的解决方案。就如同使用 JDBC 的情况,架构设计师和开发人员在使用实体 bean 时,能利用现有的关系数据库基础结构和现有的专门技术产生数据库查询。实体 bean 可以简化开发健壮数据持久性代码的过程,因为 EJB 容器提供了许多生命周期企业服务,例如安全性、资源管理、事务控制和透明的持久性。实体 bean 提供了功能强大的数据持久性解决方案,它为开发人员透明地处理大量语义和细节。这一强大功能和轻松的开发所付出的代价就是实体 bean 是资源密集型的,而且正确设置它很复杂,调试很困难。
对于 J2EE 阵营中较成熟但不以 Java 为中心的技术,Java 数据对象是一种引人关注的替代技术。JDO 的纯面向对象方法和设计的简单性使掌握它所需的适应期比其它两种持久性技术都短。但 JDO 也没有 JDBC 或 EJB 技术成熟,这导致开发人员和架构设计师在作设计和部署决定时无法获得足够有帮助的资源。而且,对于它向 Java 开发人员提供的所有易用性,JDO 要求 DBA 作出明确承诺,即为使用它必须尽快了解全新的数据管理范例。
下个月,我们将探索企业消息传递,以此来结束对 EJB 技术领域的首次探险。到那时,希望能快乐地探险!