首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

1.3  持久层和其他层

在一个中型或者大型应用程序中,按关注点组织类通常比较有意义。持久化是一个关注点;其他还包括表现、工作流和业务逻辑。一个典型的面向对象的架构包括表示这些关注点的代码层。标准的且必定最好的实践是,把所有的类和负责持久化的组件都组合到一个分层系统架构中一个单独的持久层。

在本节中,我们先来看看这类架构的层,以及为什么要使用它们。随后,集中在我们最关注的那个层——持久层——以及可以实现它的几种方法。

1.3.1  分层架构

分层架构定义了实现不同关注点的代码之间的接口,允许改变实现关注点的方法,无需明显破坏其他层中的代码。分层也决定了产生中间层依赖的种类。规则如下:

l    各层交流从上到下,一个层仅仅依赖于就在它下方的那个层。

l    每个层都不知道除了它下方的层之外的其他层。

不同的系统对关注点的组合不同,因此它们定义不同的层。一个典型、公认的高级应用程序架构使用3个层,分别用于表现、业务逻辑和持久化,如图1-4所示。

表现层

 

拦截器、工具类和辅助类

 

数据库

 

持久层

 

业务层

 

图1-4  持久层是层架构的基础

让我们深入看看图中的层和元素:

l    表现层——用户界面逻辑在最顶层。负责页面以及屏幕导航的表现和控制的代码在表现层。

l    业务层——下一层的具体形式在不同的应用程序之间很不相同。然而,业务层负责实现任何业务规则或者会被用户理解为问题领域一部分的系统需求,这一点已经得到广泛认同。这一层通常包括几种控制组件——知道何时调用哪个业务规则的代码。在有些系统中,这一层对业务领域实体有着自己的内部表示,在其他系统中它重用由持久层定义的模型。第3章会继续讨论这个问题。

l    持久层——持久层是负责向(或者从)一个或者多个数据存储器中存储(或者获取)数据的一组类和组件。这个层必须包括一个业务领域实体的模型(即使只是一个元数据模型)。

l    数据库——数据库存在于Java应用程序本身之外。它是系统状态实际的、持久化的表示。如果使用了一个SQL数据库,数据库就包括关系Schema和可能的存储过程。

l    辅助和工具类——每个应用程序都有一组基础的辅助和工具类,用在应用程序的每一个层中(例如用于错误处理的Exception类)。这些基础元素不会形成一个层,因为它们不遵循分层架构中的中间层依赖的规则。

现在我们来简单地看看可以由Java应用程序实现持久层的各种方法。别着急,我们很快就要讲到ORM和Hibernate了。通过看看其他方法,可以学到很多东西。

1.3.2  用SQL/JDBC手工编写持久层

对于应用程序员来说,处理Java持久化最常用的方法是直接使用SQL和JDBC。毕竟,开发人员熟悉关系数据库管理系统,他们理解SQL,并且知道如何使用表和外键。此外,他们始终可以使用众所周知且被广泛使用的DAO模式,来隐藏业务逻辑中复杂的JDBC代码和不可移植的SQL。

DAO是个很好的模式——因此我们甚至经常推荐把它与ORM一起使用。然而,给每个领域类手工编写持久化代码涉及的工作量相当大,特别当支持多个SQL方言的时候。这项工作通常消耗很大一部分开发精力。甚至,当需求改变时,手工编写的解决方案总是需要更多的注意力和维护精力。

为什么不实现一个简单的映射框架来适应项目的特殊需求呢?这种努力的结果甚至可以在未来的项目中重用。许多开发人员已经采用了这种方法;如今许多自制的对象/关系持久层应用于产品系统中。但是我们不推荐这种方法。优秀的解决方案已经存在:不仅有商业供应商销售的工具(非常昂贵),也有免许可的开源项目。我们确信你肯定能够找到一种满足你需求的解决方案,包括业务需要和技术需求。这种解决方案可能比你在有限的时间内能够创建的解决方案完成更多的工作,并且做得更好。

开发一套适度的全特性ORM可能要花费许多开发人员几个月的时间。例如,Hibernate大约有80 000行代码,其中有些比典型的应用程序代码更难,还有25 000行单元测试代码。这可能比你的应用程序中的代码还多。在这样一个大项目中,可能很容易忽略大量的细节——依据我们两位作者的经验!即使一个现有的工具没有完全实现你其中的两三个更奇异的需求,也仍然可能不值得去创建自己的工具。任何ORM软件都会处理单调的普遍的案例——正是削减生产力的那些案例。如果你需要手工编写某些特别的案例也可以;但是很少有应用程序是主要由特殊的案例组成的。

1.3.3  使用序列化

Java有一个内建的持久化机制:序列化提供了把对象网络(应用程序的状态)快照写到字节流的能力,然后它可能被持久化到一个文件或者数据库中。序列化也被Java的远程方法调用(Remote Method Invocation,RMI)用于给复杂的对象实现传递(pass-by)值语义。序列化的另一种用法是在集群机器中跨节点复制应用程序状态。

为什么不给持久层使用序列化?不幸的是,序列化之后的关联对象网络只能被当作一个整体访问;没有反序列化整个流,就不可能从流中获取任何数据。因而,结果字节流必须被当作不适合进行任意的搜索或者大型数据集的统计,甚至不可能独立地访问或者更新单个对象或者对象的子集。对于设计用来支持高并发性的系统来说,除了在每个事务中加载和覆盖整个对象网络外,别无他法。

鉴于当前的技术,序列化还不足以作为高并发性的Web和企业应用程序的持久化机制。序列化有一项特别的作用,是桌面应用程序最适当的持久化机制。

1.3.4  面向对象的数据库系统

由于我们是在Java中使用对象,所以如果有一种方法能把那些对象存储到数据库中、又根本不必扭曲对象模型就好了。在20世纪90年代中期,面向对象的数据库系统备受关注。它们以一个网络数据模型为基础,在关系型数据模型出现之前的十几年前,这种方法很普遍。基本的思想是存储一个对象网络,包括它所有的指针和节点,并随后重新创建相同的内存图。这可以用各种元数据和配置设置进行优化。

与其说是像外部数据仓库,面向对象的数据库管理系统(OODBMS)则更像是应用程序环境的一个扩展。OODBMS通常以一个多层实现作为主要特征,包含一个后端数据仓库、对象高速缓存,以及一个紧密结合的通过一个私有网络协议进行交互的客户端应用。对象节点保存在内存页面中,该内存页面向(或者从)数据仓库中进行传输。

面向对象的数据库开发从宿主语言绑定的自顶向下的定义开始,这些绑定给编程语言增加了持久化的能力。因此,对象数据库提供了与面向对象应用程序环境的无缝整合。这不同于当今的关系数据库所用的模型,在这里,与数据库的交互通过一种中间语言(SQL)进行,并且独立于特定应用程序的数据是主要的关注点。

有关面向对象数据库的背景信息,我们在An Introduction to Database Systems(2003)中推荐有相应的章节。

我们不想深入研究为什么面向对象的数据库技术还没有流行起来;我们将发现对象数据库还没有被广泛采用,可能近期内也不会。考虑到当前的政治现实(预先确定的部署环境)和数据独立的普遍需求,我们相信压倒多数的开发人员会有更多的机会使用关系技术。

1.3.5  其他选项

当然,也有其他类型的持久层。XML持久化是序列化模式的变形;这种方法允许通过一个标准化的工具接口来轻松地访问数据,从而解决了字节流序列化的一些限制。然而,在XML中管理数据会使你遭受一个对象/层次结构不匹配的危险。此外,XML本身也没有其他益处,因为它只是另一种文本文件格式,对数据管理没有继承能力。可以使用存储过程(有时候甚至可以在Java中编写),把问题移进数据库层。所谓的对象—关系数据库已经作为一个解决方案销售,但是它们只是提供一个更完善的数据类型系统,对于我们的问题只提供半个解决方案(和更加费解的术语)。我们确信还有许多其他的示例,但没有一种可能很快变得普及起来。

政治和经济上的约束(在SQL数据库上的长期投资),数据独立和访问有价值遗留数据的需求都要求一种不同的方法。针对这些问题,ORM可能是最实用的解决方案。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论