对象对象-关系数据库之间的映射关系数据库之间的映射
为什么对象-关系数据库的映射对于现代开发者是一件大事呢?一方面,对象技术(例如 Java 技术)是应用于新软件系统开发
的最常见的环境。另外,关系数据库仍然是许多人都青睐的持久信息存储方法,并且在较长时间内这种情况不太会改变。请继
续读下去,了解如何使用这种技术。
为什么要写有关对象-关系数据库之间的映射的文章呢?因为在对象范例和关系范例之间“阻抗不匹配”。对象范例基于软件工程
的一些原理,例如耦合、聚合和封装,而关系范例则基于数学原理,特别是集合论的原理。两种不同的理论基础导致各自有不
同的优缺点。而且,对象范例侧重于从包含数据和行为的对象中构建应用程序,而关系范例则主要针对数据的存储。当为访问
而寻找一种合适的方法时,“阻抗不匹配”就成了主要矛盾:使用对象范例,您是通过它们的关系来访问对象,而使用关系范
例,则通过复制数据来联接表中的行。这种基本的差异导致两种范例的结合并不理想,不过话说回来,本来就预料到会有一些
问题。使对象-关系数据库之间的映射成功的一个秘诀就是理解这两种范例和它们的差异,然后基于这些认识来进行明智的取
舍。
本文应该能够消除现今开发周期中一些普遍共有的误解,对对象-关系数据库之间映射所涉及到的一些问题提供了切合实际的
看法。这些策略基于我的开发经验,项目范围从小到大,涉及金融、销售、军事、远程通信和外购等行业。我已对使用
C++、 Smalltalk、Visual Basic 和 Java 语言编写的应用程序应用了这些原则。
如何将对象映射成关系数据库如何将对象映射成关系数据库
在这一节中,我会描述一些将对象成功映射成关系数据库所需的基本技术。
将属性映射成列
在关系数据库中实现继承
将类映射成表
映射关联、聚合和组合
实现关系
将属性映射成列将属性映射成列
类属性将映射成关系数据库中的零或几列。要记住,并不是所有属性都是持久的。例如, Invoice 类会有 grandTotal 属性,这个
属性由其实例在计算时使用,但它不保存到数据库中。而且,某些对象属性本身就是对象,例如 Course 对象有一个作为属性
的 TextBook 实例,它映射为数据库中的几列(实际上,很有可能 TextBook 类本身就将映射成一个或多个表)。重要的是,这是
一个递归定义:有时属性将映射成零或者多列。也有可能将几个属性映射成表中的单一列。例如,代表美国邮递区号代码的类
可以有三个数字属性,每个都表示完整邮政编号代码中的每一部分,而邮政编号代码可以在地址表中作为单一的列存储。
在关系数据库中实现继承在关系数据库中实现继承
在将对象保存到关系数据库中时,继承的概念中发生几个有趣的问题。(请参阅参考资料中的 "Building Object Applications
That Work"。)问题从根本上归结为解释如何在您的持久模型中组织继承的属性。解决这个难题所用的方法会对系统设计有很
大影响。将继承映射到关系数据库中有三种基本解决办法,为更好地理解它们,我将讨论在图 1 中显示的映射类图表的优缺
点。为简化问题,我没有为类的所有属性都建模;也没有为其完整签名或任何类方法建模。
图图 1. 简单类层次结构的简单类层次结构的 UML 类示意图类示意图
将类映射成表将类映射成表
类到表的映射通常不是直接的。除了非常简单的数据库以外,您不会有类到表的一对一映射。在以下章节中,我将讨论为关系
数据库实现继承结构的三种策略:
整个类层次结构使用一个数据实体
每个具体类使用一个数据实体
每个类使用一个数据实体
整个类层次结构使用一个数据实体整个类层次结构使用一个数据实体
使用这种方法,您可以将一个完整类层次结构映射成一个数据实体,而层次结构中所有类的所有属性都存储在这个实体中。图
2 描述了采取这个方法时图 1 的类层次结构的持久模型。请注意,为表的主键引入了一个 personOID 列 - 我在所有解决方案中
都使用 OID (没有商业含义的标识,又称替代键),只是为了保持一致和使用我所知道的向数据实体分配键的最好办法。
图图 2. 将类层次结构映射成单一数据实体将类层次结构映射成单一数据实体