开发人员 趋势

设计模式

作者:Cameron O'Rourke

应用程序在不断更新换代,但数据将永远留存。

在构建应用程序时,你是从一个经过可靠设计和测试的数据库模式开始,还是从基于机器生成的模式这样不稳定的基础开始?

通过本文,我希望你能够将数据库模式设计作为创建任何高质量应用程序的一个重要部分。我将向你展示我的典型工作流,并向你提供几个我认为很有帮助的小技巧。

状态还是日期?

虽然面向对象的技术为应用程序开发人员带来了很大的实惠,但是它也导致了一些数据管理问题。

在对象世界中,数据被简单地看作对象状态,这是一种实施正确的对象行为的方法。好的对象设计会封装对象或者将对象状态隐藏到界面(方法调用集)后面。

把对象状态映射到关系表的现代对象/关系型框架尽力使面向对象的开发人员不再需要设计关系型数据库、创建SQL语句和了解其所选择的数据存储的功能与性能特征。

像Java 2平台企业版(J2EE)实体Bean这样的框架能够生成适合维持对象状态的数据库模式。在运行时,可以自动构建SQL语句,以插入、更新、删除和查询数据库行。

但这是个好主意吗?当你放弃数据建模、关系的忠诚度(relational fidelity)、手工SQL及特定厂商的数据库特性时,你放弃的是什么?

不要生成,而是要建模

事实上,机器生成的模式不能与一名技术娴熟的数据建模师精心设计的模式相匹配。通过了解商务领域的数据要求,数据建模师可以创建出超越现有应用程序的模式。好的模式提取了特定应用程序的构造元素,以解决各种商务问题,并且随着时间的推移,更好地经受环境的变化。

Conceptual view of Designer
图1:设计器(Designer)信息库与工具的概念性视图

"应用程序开发人员必须设法了解他们本身并不拥有数据,而是企业拥有数据,他们的应用程序只是'借用'这些数据。"Tom Kyte (asktom.oracle.com)说,"应用程序可能不会留存,但数据将永远存在,并不是只有应用程序才需要这些数据。"

你的SQL,你的数据库

很多持久性框架使你几乎或者根本无法控制正在执行的SQL。这就限制了你调优SQL和准确地表达你正在寻找的结果的能力。在提供答案方面,数据库非常有效,但是你必须通过适当的SQL查询告诉它你希望获得的结果。

另一个限制是应用程序经常需要进行框架无法生成的复杂查询,如在一个分层任务列表中累计成本的查询。

请选择一个使你能够忽略用于查询的SQL的框架,如Oracle Business Components for Java (BC4J)。其他控制SQL的策略还包括将所有SQL封装到数据库存储程序中,并在基表中大量使用视图。

生成的模式很少能够合理地使用关系数据库特性,这会对性能产生极大的影响。数据库返回结果的效率很高,但是只有当你为其提供选项时,它才能够做到这一点。对于基于成本的优化器来说,关系连接、视图、聚合、子查询、CONNECT BY 及外部连接等都非常有用,但是它们通常会被持久性框架忽略。

特定厂商的数据库特性几乎不会用于生成的模式中。很多框架都不使用数学上的专用函数、字符串处理、安全性、外部处理、空间和时间计算以及统计与分析等。不充分利用数据库的结果是会产生过多的代码,并导致更高昂的开发和维护成本。

借助Oracle设计器建模

虽然为一个基本模式建模能够使用的工具很多,但我使用了Oracle设计器(Oracle Designer),因为它对Oracle数据库结构提供了最佳的支持。借助Designer,我可以构建一个包括视图、对象类型、序列、检查约束、用户和角色、数据库触发器以及存储程序在内的完整Oracle模式模型。

Oracle 设计器是依靠一个相当大的信息库工作的绘图工具、模型转换器及代码生成器的集合。信息库中有大约50种不同的对象类型。在图 1中,我对这些对象类型进行了分类,并通过设计器工具将它们一一展示出来。

设计器将信息库划分为概念对象和物理对象。概念对象对于(如图1上半部分所示)捕获商务模型、编目需求和进行应用程序设计非常有用。物理对象(如图1下半部分所示)包含了大量详细的信息,并用于生成实际的代码资产及数据库模式对象。

我一般从创建一个实体关系图(ERD)着手构建新的应用程序。实体是一些概念性数据结构,使你能够在无需考虑如何通过行和列来显示数据的情况下,考虑应用程序需要处理的数据以及数据之间的关系。在ERD上,无需为每个属性建模,也无须使用主/外键。ERD对于与商务用户进行高水平的讨论来说,也是非常理想的。

在任何地方,你都可以运行数据设计转换器(Data Design Transformer),它将生成一套带有前缀列名、索引及主/外键的完整的数据库表。如果你已经对超级类型或子类型,或者任何多对多关系建模,那么数据设计转换器将把这些构成元素分解成相应的关系表结构。更妙的是,这不是一次性操作--你可以在更新模型时再次运行数据设计转换器。它总是向你展示将要做什么,以便你能够更改建议,避免基于模式的任何工作惨遭失败。

接下来,我将使用设计编辑器(Design Editor)为模式建模。表之间的关系已经从ERD建立起来了,所以在此我主要是充实细节。(如果你只使用设计编辑器来填充模型并生成数据库模式,你将仍然拥有一个比其他许多开发项目都好的基础。)这里有一些小技巧:

  • 为每个表和列输入注释。这些注释将被转移到数据库中,你可以将它们用作应用程序中的帮助文本。描述表或列在现实中代表什么,其中包括数字计量单位。一定要标注空值的意义是什么。
  • 域是一个列参数的命名集。使用域来保持一致性,特别是对于主/外键列。
  • 如果某列采用离散的编码值,那么在Allowable Values对话框中将它们全部指出来。设计器将创建一个包含所有编码值的表,你可以将它用作弹出列表和帮助文本。
  • 如果某列将包含数值范围,那么请在Allowable Values 对话框输入这个范围,并选择Hard Code,以便设计器生成一个检查约束。
  • 至于主键值,可以考虑让数据库通过使用SYS_GUID()默认值来指定。这可以保证你的主键值在你的表中、在多个表中、甚至在不同的数据库中都是独一无二的。如果你正在构建一个分布式系统,那么这一步至关重要。

工作流

完成了一系列的建模工作后,我需要将设计器模型转变成一个数据库模式。设计器中的数据库模型相当完整,因此在我的工作流中,我将它用作"事实点"(point of truth)。设计器生成实际的数据定义语言(DDL),然后我将该语言存储在一个源控制系统中。我可以选择使用设计器将模式直接部署到开发数据库中。
下一步

向Cameron咨询
devtrends.oracle.com
技术专家Cameron O'Rourke回答你的问题并为你提供更多的开发资源。

阅读有关Oracle Designer的信息
otn.oracle.com/products/designer

Oracle 设计器的一个强大特性就是能够将模型与目标数据库模式进行比较,并且只输出使模式与模型保持一致所需的DDL更改。在我的工作流中,我首先会做出设计器中模式所需的任何更改。然后,我将这些更改应用到开发数据库中,并保存SQL脚本,用来修补其他系统。

测试

部署完模式并使其运行在数据库上后,我便对其进行测试,并向开发人员说明如何使用它。

  • 我为任何公用事务或包含多个步骤的任何事务编写了PL/SQL存储程序,而不是顺其自然。
  • 我编写了示例查询来测试我的模式的性能和作用。我创建好的示例数据,以便开发人员能够知道如何更好地使用模式。
  • 我编写了测试脚本来检查数据的完整性,并检查了每个数据完整性机制。
  • 我检查了安全性,并编写了测试脚本以检查可能出现的安全性问题。

你已经花钱购买了数据库

我认为你需要通过一个可靠的数据库模式着手组织任何J2EE项目。让容器管理的持久性或对象关系型框架将数据库作为一个"位存储桶"(bit bucket)来使用是一个严重的错误,这样的错误会导致性能低下、中间和客户层代码过多以及产品面市时间过长等。你已经花钱购买了数据库,为什么不对它进行深入研究呢?

请让我通过 devtrends.oracle.com更多地了解你关于这个主题的见解。

Cameron O'Rourke ( devtrends.oracle.com)成为Oracle技术专家已经有十一年多了。

E-mail this page