一、引言
现代的企业开发中,越来越多地引入了多层架构设计模式,即使是小型的企业信息系统也逐渐向多层架构发展,以满足系统的可伸缩性以及可维护性。目前企业开发的平台占主导地位的是
J2EE 和 .NET 两大平台,本文并不是去对比两大平台的优缺点,以免引发宗教式的争论,而是在两大平台的基础上探讨如何进行数据库的设计,将设计模式引入到数据库设计中,以期达到良好的、可管理、可伸缩的数据库设计。
传统的数据库设计理论,更加关注的是数据库设计范式,这是数据库设计必须要遵守的规则:
第一范式(1NF):在关系模式R中的每一个具体关系r中,如果每个属性值都是不可再分的最小数据单位,则称R是属于第一范式的关系。
第二范式(2NF):如果关系模式R(U,F)中的所有非主属性都完全依赖于任意一个候选关键字,则称 R是属于第二范式的。
第三范式(3NF):如果关系模式R(U,F)中的所有非主属性对任何候选关键字都不存在传递信赖,则称 R是属于第三范式的。
一般认为设计数据库时能够达到第三范式即可,这也是大部分数据库原理课程所要求的数据库设计结果。但现代关系数据库管理系统中,除了支持数据库中的数据查询、更改、插入和删除外,更有强大的企业级功能支持,像存储过程、触发器和分布式查询处理,无疑,我们的数据库设计如果只满足几个范式的话,充其量只是完成了数据的存取要求,而无法和企业程序良好的结合。在设计企业应用中,数据库是企业应用中最重要的一层,是企业应用的信息起点和终点。如何将业务逻辑在数据库系统设计中正确、良好的表达,不仅涉及到系统实现的不同方式,也涉及到企业应用的成功与否。
本文试图探讨在数据库设计中如何应用设计模式理论,形成一种数据库设计模式,以避免业务逻辑层对数据库层的信息耦合,达到业务逻辑在不同层之间的正确转移与实施。
二、分布式多层应用中数据库设计的疑问
现代的企业应用程序大多采用分布式多层应用模式。如下图所示:
从上面的示意图中可以看出,无论是微软的 .NET 平台还是 J2EE 平台都表现出将业务逻辑单独放置在业务逻辑层中的意图,也即
.NET 平台中的 Web Service,J2EE 平台中的 Enterprise Java Bean。
J2EE 平台发展较早,并且理论非常成熟,很多技术和架构都在 J2EE 中产生,然后才有相应的 .NET
移植与实现。在 J2EE 体系架构中,核心的是 Enterprise Java Bean 技术,而 Session
Bean 更是成功的设计。在 J2EE 中,利用 Entity Bean进行了 O/R 映射的尝试,但因为
Entity Bean 的设计复杂以及无法进行单元测试等缺点,在 J2EE 社区中颇多微词,也导致了 Hibernate、JDO
等轻量级 O/R 框架的产生。而在微软的 .NET 平台中,也出现了 NHibernate 的移植框架,微软本身也在进行
Object Spaces O/R框架的开发。
通过研究O/R 映射,让程序员和设计者产生了这样一个感觉:无论是 Entity Bean、还是 Hibernate
和 JDO,都强调 O/R 映射关系,让程序员和设计者可以用面向对象的思维方式来考察系统,而不用关心数据如何在底层存储,甚至我们只要在系统中设计好对象实体,然后利用
O/R 映射去自动实现到数据库的映射即可,程序员不需要关心数据库,不需要知道任何 SQL 的语法,只需要通过专门的
EJB-QL 或者 HQL 语言进行数据的处理即可,而无需在程序中书写任何的设计数据库存取的代码。这样编写的程序有利于移植,如果需要更改数据库系统,仅仅重新改写
EJB-QL 或者 HQL 语言既可。
虽然看起来很美,但这却是一个美丽的谎言。
首先,在企业应用设计中,当选择了一个关系数据库系统后,在实施时企业将花费大量的资金购买数据库系统使用许可,而且数据库系统的实施、安装、日常维护也需要专门的人员来完成,更换数据库系统意味着企业的巨大损失,基本上不可能出现更换数据库系统的情况。
其次,大型数据库管理系统有着良好的设计和优化功能,而且不同的数据库系统有着自身的特点,很多特性是独有的,是不可移植的。采用
O/R 映射会损失数据库系统所特有的强大的功能。
第三,无论在进行系统设计时如何优化性能,O/R 映射最终都要转化为实际的数据库连接,进行实际的数据库操作,而这些任务是无法和数据库系统内部的存储过程、触发器的性能相比较的,而且即使通过连接池,也会增加数据库连接的负荷。
所以,良好的数据库设计仍然是企业应用中非常重要的步骤。
三 在数据库设计中应用 Facade 模式
当前系统设计中有大量的设计模式,Facade 设计模式更是深入人心。Facade模式描述为:“为子系统中的一套接口提供了一个统一的接口。Facade
定义了一个更高层次的接口,使子系统更容易使用。”在系统设计中,Facade 是应用最广泛的设计模式,利用
Facade 模式的思想把构成子系统的一套业务对象“包装”在Facade 接口中。这样,Facade对象作为客户端访问业务对象的拦截器,屏蔽了业务对象。客户端访问Facade对象来代替访问底层的业务对象,当一个客户端需要调用多个业务对象的方法时,它只需要进行一次粗粒度的远程方法调用,将请求送给Facade
对象, 再由Facade 对象通过本地方法调用,调用相应的业务对象,执行其方法。这样就减轻了网络负载,提高了系统性能。并且当底层业务对象的方法改动时,只需要修改
Facade 对象,而客户端可以保持不变。这就减少了客户端和业务对象之间的耦合度,同时客户端也不必管理事务的细节。如下图所示:
由 Facade 设计模式我们可以看出,如果将数据库系统认为是一个底层的业务系统,我们应该在设计数据库系统时隐藏底层的细节,而将所有对数据库进行的增、删、改、查询操作统一到一个
Facade 接口上来,这样在系统设计的过程中,所有与数据库系统打交道的业务组件无需关心底层的数据库存储方式,而是将底层的数据按照系统实体的方式展现出来,再通过
Facade 接口进行变换,将实际的实体提交给业务组件接口或者将实体持久化到真正的数据库表当中。
比如,在设计学生选课管理系统中,底层的数据表可能包括课程表、学生表、选课表以及成绩表,但对外表现出来的实体应该只有学生和课程两个实体。然后可以通过一个存储过程暴露出来一个学生选课的功能,在业务组件中调用。同时应设计触发器,当插入选课信息到选课表的时候,在相应得成绩表中插入相应的记录。而在业务组件端,仅仅看到底层数据库系统暴露出来的一个功能,即使数据库系统的设计发生变化,也不会影响业务组件的功能。
随着 SQL Server 2005 的发布,已经可以在 SQL Server 2005 中使用 .NET
CLR 来进行数据库的编程,这对数据业务逻辑的封装提供了更好的支持。Oracle 已经支持 Java,并且也在进行
.NET CLR 的集成,IBM 的DB2 也有类似的功能。
采用Facade设计模式,能够较好的隔离底层数据库系统与业务组件之间的耦合,但物极必反,过度的使用存储过程也可能带来不必要的设计麻烦。在数据库设计中,适当的暴露底层的视图也是一种良好的设计风格。一个全面的、良好的设计才是系统成功的保证。
|