将对象映射到关系数据库.doc

上传人:scccc 文档编号:12728603 上传时间:2021-12-05 格式:DOC 页数:38 大小:1.27MB
返回 下载 相关 举报
将对象映射到关系数据库.doc_第1页
第1页 / 共38页
将对象映射到关系数据库.doc_第2页
第2页 / 共38页
将对象映射到关系数据库.doc_第3页
第3页 / 共38页
将对象映射到关系数据库.doc_第4页
第4页 / 共38页
将对象映射到关系数据库.doc_第5页
第5页 / 共38页
点击查看更多>>
资源描述

《将对象映射到关系数据库.doc》由会员分享,可在线阅读,更多相关《将对象映射到关系数据库.doc(38页珍藏版)》请在三一文库上搜索。

1、满江?I翎译团队:vwwiedsa购.coni#将对象映射到关系数据库:对象/ 关系映射(0/R Mapping)详解大多数现代商业应用开发项目使用而向对象技术,比如采用Java或者C#來创建应 用软件,同时使用关系型数据库來存储数据。但这并不是耍说你没有其它选择, 也有许多应用程序是使用面向过程的语言开发,比如COBOL,而H也有许多系统 使用对彖型数据库或者XML数据库來存储数据。然而,因为而向对彖和关系数据 库技术到目前为止己经成为一种事实上的标准,在本章节中我假设你正在使用这 些技术。如果你采用其它的存储技术,本文甲.的许多概念仍然适用,只需耍做一 点点修改(不必担心,Realisti

2、c XML总括了对彖与XML映射的相关问题)。在项冃组通常用來创建以软件为某础的系统时,那吐技术中,存任着面向对象技 术和关系型技术Z间的阻抗火配。不过这种阻抗失配很容易被克服,秘诀在J:两 点:你盂要理解把对象映射到关系型数据库的过程,以及如何公实现这些映射。 在本章节电,“映射”一词是用来表示如何把对象和对象之间的关系对应到数据 库表以及表之间的关系。你将很快发现这并不像听起來的那样简单易懺 尽管它 实际上也不是那么的槽糕。目录 敏捷DBA的角色 基本概念o Shadow 彳二息o映射元数据o 如何使映射适介全过程继承结构的映射o 整个层次结构映射到张农o 每个八体类映射到单独的张衣o毎个

3、类单独映射到一张表o将类映射为个通用的衣结构o 筝巫继承映射O 映射策略Z间的比较映射対彖关系O关系的类型O 如何实现对彖关系O 如何实现关系数据咋中的关系O关系映射 一对一映射 一対多映射- 多对多映射O 映射有序集合O映射递归关系 映射类作用域(Class-Scope )屈性性能调优o优化你的映射O 延迟读取 为 什 么 数据Schema不丿卫 该 上 导 対 象Schema 实现方式对对彖的影响 模取驱动体系结构('IDA: Model Driven Archhecnue)的含义映射技术模式化参考文献和阅读推荐1敏捷DBA的角色图1显示了一个敏捷DBA在映射对象到关系数据库的过程

4、屮所扮演的角色。英中我们关心 三个主要的活动。1. 映射,基木的目标是决定一个冇效的策略來持久化对象数据。这包括保存单个对彖 的属性以及对彖之间的关联,同时也包括那些类之何的继承结构。2. 实现映射3性能调优在图1屮我们注意到有一个有趣的事悄,敏捷的DBA和应用程序开发人员在在这 三个主耍活动中都在一起工竹虽然敏捷的DBA应该确保映射的有效性,但他们 实际上并不是独门对其负责的。与他人协同工作而不单打独斗正是敏捷软件开发 成功的关键所在。图1.映射时敏捷DBA的角色。满江?I翎译团队:vwwiedsa购.coni32. 基本概念在学习如何把对象映射到关系型数据库的过程中,通常是从映射一个类的数

5、据属 性开始的。一个属性可以映射到关系型数据库甲.0个或考多个字段。谙记住,不 是所有的属性都是持久性的,其中的一些只是用做临时计算的。例如,在你的应 用程序中1个Student对象可能盂耍有一个'I'均分(averageMark)屈性,但并 不需耍存储到数据库电,因为它是由应用程序计算得到。一个对象的某些属性可 能木身也是对象,比方说一个CusSwer对象拥有一个Address对象作为其属性 这其实反映了两个类之间霜耍被映射的关系,Address类本身也需耍被映 射。重要的是这是一个递归的定义:任需耍的地方,一个属性将被映射到0个或 者多个字段。最简单的映射就是把-个属性映射

6、到一个字段。当双方拥有一样的基本类型的时 候,这共至可以变得更简单。例如,双方都是date类熨,或者属性是string 类型而字段是char型,或者加性是number类型而字段是float类型。映射术语映射(动词).指的是如何把対象和对彖Z间的关系持久化到水久存储设备(这在里是关系 型数据库)中的行为。映射(名词).如何将对彖的属性或关系持久化到水久存储设备的定义的关系。属性.数据属性,是实际的物理属性,例如一个fhstName字串;或者是由某个操作实现的 虚拟属性,例如getTotal ()方法返回一个订单的总数。属性映射.描述如何持久化对彖的属性的映射。关系映射.描述如何持久化两个或者更多

7、的对彖Z间的-个关系(关联,聚介或者组合)。把类映射到表上会让许多事情思考起來更简单,有时候的确是这样映射的,但并 非总是这样克接,除了少数特别简单的数据库,你将不会有机会在类和表之间进 行简单的一一映射。虫这章的后面你将看到继承映射。但是,就这一罄章全面來 看,通常对丁初始的映射,单类映射到单表是适用的(性能调优可能会促使你对 映射进行重构)。现在,让我们从简单事物开始。图2显示了 2个模型,一个血的类图和一个遵 循数据建模规则的物理数据模型°这两张图描绘了一个简单的订单系统。你 可以看到如何映射类的屈性到数据库的字段上。例如,图甲.显示Q辺曰淡的 dateFulfilled性映射

8、到OrderH.的 dateFulfilled-f段,Orderlten的 刀血血re 属性映射到 Order的 Number Orderecf 段。图2.简单映射的例子«Physical Data Model»«Class Model»OrderOrderld: INT24 «PK» DateOrdered: DateDateFulfilled: DateTax: Float(ordered 1 产OrderitemOrderld: INT24 «PK» «FK» ItemSequence:

9、INT24 «PK» ItemNo: INT24 «FK» NumberOrdered: INT24 LastUpdate: TimeStampSubtotalBeforeTax: Float ShipToConUctID: INT24 «FK» BillToContactID: INT24 «FK» LastUpdate: Time Stamp满江纟翻译团队:vwwiedsa购com慕本加性的映射很容易确定,有儿个原因。忡先,两个模型中使用相似的命名规 则,这是采用散捷建模实践“建模标准化”的一个方而:其次,通常

10、是同一群人 创建这两个模型。而当人们任不同的团队工作的时候,很容易做出不同的方案, 即便是在各个团队本身的T作都很出色的时候也是这样,因为他们沿着不同的方 向进行决策:第三,一个模型很容易用來驱动另一个模型的开发。在“不同的项 I需耍不同策略”一文屮我讨论了当你创建个新系统的时候,你的对彖schema 应该主导你的数据库schema的开发。图2里而显示的两个schema虽然很相似,但还是存在一些区别。这些区别意味 着不存在一个完美的映射。2个schema间的不同点有:在对彖schema里,tax仃多个属性而数据schema里只仃一个。当对彖被保存时, Order 里tax的3个属性将被相加并保

11、存到sx字段里。然而,当对彖被读进内存 时,这3个屈性将需要被计算(或者使用一个延迟初始化的方式,这样每个属性仅 仅在第一次被访问的时候计算)。一个像这样的schema上的区别说明数据库schenia 需要重构,把tax字段分成3个不同的字段。 数据Schema标明了键而对彖Schema没有。表中的每一行都有一个全表唯-的主键 值,行间的关系被用外键实现。而对对象之间的关系,是通过使用引用而卄使用 外键。这暗示为了完整的持久化对彖和它们的关系,对彖蛊耍知道数据库里面用來 标识它们的键值。这些额外的信息被称为“shadow信息”。 每个Schema里而使用了不同的类型。Order里subTota

12、lBeforeTax属性是Currency 类ifi Order表l subTotalBeforeTax字段是float空。'耳你实现这个映射,你需要 在这些数据的表示形式Z间进行无损转换。2. 1 Shadow 信息Shadow信息是指那吐为了将对象持久化,而不得不维持的非业务数据。这通常 包括主键信息,特别是当丄键是没有业务含义的代理键值时;并发控制标识例如 时间戳或者增量计数器;以及那些版本号。例如,在图2你可以看到QMer农有 一个力的字段作为主键,一个血r类所没有的tUpda沧宁段被用来乐观 并发控制。为f lE确持久化一个gder对象,就需要实现包含这些信息的shadow

13、属性。图3显示一个对0皿冶和Orderitem进行详细设计的类模熨。和图2相比,有一 些修改。首先,新的图显示了类需要正确持久化白己所需要的shadow H性。 shadow Id性是实现可见的,在它们的名字前而是一个空格而不是一个"一"号, 同时被指定了<<persistence>>进行说明(这不是一个UML标准)。第二,它显 示需耍在两个类之间实现联系所需耍的辅助(scaffolding) J/4性。辅助属性,例如 Order 4.面的"/mTYms列表,同样是实现口见的。第三,一个getTotalTax() 操作需要被加到Order类

14、里來计Order表中tax字段所需要的值。这是为什 么我用屈性映射这个词來代替属性映射一你所想耍做的是映射一个类里而的属 性到数据库电的字段上,有时这些属性是通过简单的加性实现的,而其它某些时 候是由一个或者多个操作所决定的。3.在一个类图里包含"shadow信息"Order diteomenid: catu date tinned: coia-TodeniTS t: currena;-itateisi: Cuming -IwalTSs; Cumn-sy-lubbbl&?forTai; Cumrw; il(pT» FVrionbill To: FMrion

15、 orderrtem i: Xrtdor orderiD: int «Ririi rtenG®” laiilipdato: catenmeFm ifence»e>oroewCrdrtte'm-numbrordd: mtordir: orderl 伽;lt*mlaitUpdat*; Cg-teTlm <-<P&nliWnG»gehoi3iT3i(): Qjrrenc;" Pril itence»我还没有讨论的一种shadow信息是用一个boolean类型的标志來表示当前一个 对象是否在丁数据库中。这电的

16、问题是当你把数据保存到一个关系型数据中, 如果原先的对彖是从数据库中获取出來的,你需要便用一个SQL update语句來 保存数据,否则应该使用SQL insert语句。一个普通的解决方法是为每个类实 现一个isPersistent的boolean型信号标志(图3里没有显示),当数据是从 数据库电面读取的时候把它的值设置成true,如果对象是新创建的话则设置为 falseo在UML社区电面的一个通用的风格约定是在类图电不显示shadow信息,例如键值 或并发标识。类似的,通常也不显示支撐代码。因为每个人都知道你需要做这种 事情,所以何必浪费时间去显示这些明显的事实呢?Shadow信息不必用业务

17、对象(business object )來实现,不过那样你的程序就 要在其他地方处理这个问题。例如,在Enterprise JavaBeans (EJBs)也你把主 键保存在EJB以外的主键类(primary key class)里,独立对彖引用和关的上键 对象。而进一步的,Java Data Object (JDO)则是在JDOs电面实现shadow信息, 而不是在业务对象(business object )里。2. 2映射元数据图4显示了元数据(meta data),这些是代表持久化图3 .Order Order Item 类所需耍的属性映射。元数据是关数据的信息。因如卜原因使得图4显得很

18、重 耍的。首先,我们需要某个方式來表现映射。我们可以把2个schema并排放在一 起,就像图2里而那样,然后在它们之间画线,但是这很快会变的非常复杂,而 另外一个选择是像图4里面这样列表;第二,映射元数据的概念对持久化枇架的 功能是非常取耍的,这是一个可以让敏捷数据库技术发挥作用的数据座封装策螫 图4.代表属件映射的元数据PropertyColumnOrder.orderlDOrder.OiderlD满江?I 翎译UlliA: vwwiedsa购.com#Order.dateOrdeiedOrder.DateOrderedOrder.dateFulfilledOrdei-DateFulfill

19、edOrdcrgetTotalTaxOOiderTaxOrder.subtotalBefdreTaxOrder. SubtotalBefoi eTaxOrder.shipTo.peisonnDOrder. ShipToC ontactIDOrder.billTo.persoiiIDOrder.BillToContactlDOrderlastUpdateOider.LastUpdateOideiltem.ordeiedOrdeiItem.OideiIDOrdei.oideiltems.position(oiderltem)Ordeiltem.ItemSequenceOrderltem.item.

20、numberOrderltem.ItemNoOrdeiltem.numberOrderedOrdeiltem.NumberOrderedOrdeiltem.lastUpdateOideiItem.LastUpdate我采用的命名规则是非常片接了当的:Order, da teOrdered扌S得.是Order类甲. 的da teOrdered屈性。类似的还有,Order. DateOrdered指得是Order表甲.的 Da teOrdered 段。Order, get To tai Tax ()指得 Order 里的 getTotalTax ()操 作而Order. billTo. perso

21、nlD则是被Order. billTo屈性引用的Eersg对象里 的personlD J/4性。看起來最难理解的加性是Order, orderltems. posi tion (orderItem),它指向在将要保存的 Orderltem 实 例里Order, orderltems列表中的位置。图4喑示了面向对象技术和关系型技术Z间一个故重要的阻抗火配。Classl.iJ时 实现行为和数据,而关系型数据库的表仅仅保存数据而已。这导致当你映射个 类的属性到关系型数据库时,你也需更映射那些操作到数据库字段上,例如: getTotalTax()和position。虽然在这个例子电面没有出现,但是你常

22、常需要 映射仅代表一个屈性网个操作(operation)到一个字段个操作是设置值如:setFirstNameO,而另外一个是获取值,如getFirstName().这些操作通常 分别被称作 setter 和get ter,或者 mutator 和 accessor.无论何时,一个键值都耍被映射到类里的一个履性上,例如在Orderltem. ItemSequence 和 Order, orderltems. posi tion (orderltem)i. |nj 映射,这实际是关系映鮎的一部分工作,将在本章的后面进行讨论。这是因为在 关系数据库里通过使用键值來实现数据间的联系。2. 3如何使映射

23、适合全过程参看文草http:/www. agiledata. org/essays/evolutionaryDevelopment. html。3. 继承结构的映射由丁关系数据咋不是生來就支持继承的,这就强制你必须将对彖schema的继承结 构映射到相应的数据库schema中去。多半是因为不牢幕的基类(译注:不牢幕的 慕类是指,有时皋类很难修改,因为一 4修改某类,子类就容易出错)的原因,面向对象社区不太提倡使用继承,而我的经验表明:Z所以出现这个问题,是因 为而向对彖的开发者们大多缺乏封装的技巧,而非继承概念本少出了问题 (Ambler 2001a)o我想说的是,事实上,你只需耍做少量的工作

24、,即可将一个 继承层次映射到关系数据库中去,而这并不会影响你在合适的地方运用继承。把对象存入关系数据库时,继承的概念会带來-些有趣的变化。如何在数据模型 中组织那些通过继承而得到的属性?本节中,你将看到用來解决如何将继承关系 映射到数据库的三种皋本方法,以及第四种补充方法,它不限继承映射。这些 方法如下所示:整个类M次结构映射到张表每个八体类单独映射到一张表毎个类单独映射到一张表所冇类映射到一个通用的表结构如图6所示,有两个版本的类层次结构,我们将通过讨论如何映射这两个结构, 來深入了解每种方法。第一个版本描述了三个类:一个抽象类Person,和两个具 体类Employee和Customero

25、之,所以知道Person是抽象类,是因为在图屮它用斜 体表示。在鮫早版本的UML中,会用约束“absuact”來表示抽象类。笫二个版 本在第一个版本的基础上,往类层次结构中添加了一个新的具体类Executive. 旨在描述,当实现了第一个类层次结构之后,有了一个新的需求,耍求为雇员中 的执行主管,而非普通雇员,颁发固定的年度分红。类Executive就是为了满足 这一新功能而添加的。简单起见,我没有对这些类的所有屈性、属性的完整签名,以及类的任何操作进 行建模。而这幅类图恰好足以满足我的日的,换句话说,这是一个敏捷的模型。 此外,这些类层次结构本应该用分析模式中的模式(Fowlei 1997)

26、 Business EH叮模式(Amble】 1997)。我并没有这么做,因为在这电,我并不是为了说明 分析模式的有效应用,而是用一个简单的例子來说明继承层次结构的映射我 总是遵循敬捷建模(AM)的“每次只针对一个目标建模”(Model With A Purpose) 的原则。图6. 一个简单类层次结构的两个版本詞江纟翻译U11IA: vwwiedsa购 com谋用继承也会带來问题一比如,图116的层次结构木应该通过Pd/7v (Hay 1996. Fowlei 1997)模式或Business Entity' (Ambler 1997)模式进行更好的建模。举例来说,白人可能既是 库员

27、乂是顾客,为此你耍在内存屮保留多个对象,而这可能会给你的应用程仔带來问题。我 选择这个例了,是因为我需要-个简单的,易理解的类层次结构來进行映射。3.1整个层次结构映射到一张表按照此策略,把所有类的所冇屈性都“储到一张表中去。当采用这种方法时,图 6中的类层次结构对应的数据模熨如图7所示°这是非常氏观的方式,每个类的 属性都存储到表Person中,表名垠好用类层次结构中根类的名字來命劣。图7映射到一张表詞江纟I 翻译UlliA: wwwiedsapmcom-#-詞江纟I 翻译UlliA: wwwiedsapmcom-#-PersonPersonPOID «PK»

28、PersonType NamePreferences SalaryPers onPersonPOID«PK» PersonTypeNamePreferencesSalaryBonus詞江纟I 翻译UlliA: wwwiedsapmcom-#-詞江纟I 翻译UlliA: wwwiedsapmcom-#-表里多加了两个字段PersonPOID PersonType。图中,衍型(stereotype)«PK»说明第一个字段是表的主键,第二个字段是标识代码,用來指明一个人是 顾客还是雇员,抑或两者皆是。PeTS6?P07P是一个代理键(surrogate key

29、), 它是持久化对象的标识(POID, persistent object identifier),通常简称为 刘象标识(OID, object identifier)。本应该使用可选衍型(stereotype) «Surrogate»來标示的,但P0ID已经暗示了这层意思,这表明,这类衍型(stereotype)只会无谓地使我们的类图更复杂(参见AM实践“简单地描述模型” (Depict Models Simply)。数据建模101 ( http:/www. agiledata. org/essays/dataModelinglOl. html )详细讨论了 代理键(su

30、rrogate keys)的相关内容。用来识别对象类型的字段PersonType必需的,这个对象可以由给定的数据库中 的一行数据实例化而來。例如,取值为啟示该人是雇员,C表示是顾客,戒IJ表 示既是雇员乂是顾客。这种方法看似直观,但当类型数H和类型间联合越來越多 的时候,这种方法就渐渐变的力不从心了。例如,添加执行主管的概念,需耍添 加一个码值,比如以,睞代表。对丁值万來说,它代表的是既是屣员乂是顾客,此 时就显得有点不伦不类了。此外,有些(类间)联合中可能会包括执行主管,比 如,一个人既是执行主管乂是顾客也是很合乎情理的事情,这种情形也需耍一个 码值來表示。对丁各种类型联合的帖况,应该考虑使

31、用“用布尔值來代替类型码” (Replace Type Code With Booleans)的数据库重构技法,如图8所示。为了简单,没有包含那些需要并发控制的字段,比如位图3表中的时间戳字段, 同时,用丁数据版本跟踪的字段也没有包括在内。图& 一种重构方法PersonPersonPOID «PK» IsCustomer IsEmployeeName Preferences SalaryPers onPersonPOID «PK» IsCustomer IsEmployee IsExecutive NamePreferences Salary B

32、onus詞江纟I 翻译UlliA: wwwiedsapmcom-13-詞江纟I 翻译UlliA: wwwiedsapmcom-#-3.2每个具体类映射到单独的一张表这种方法为每个具体类创建一怅表,每张表既包扌舌对应类门己实现的那些屈性, 也包括它继承下來的那些属性。采用这种映射方法,图6中的类层次结构所对应 的数据库物理数据模型如图9所示。每个具体类Customer和 创刃oyee都有对 应的映射表,对象从这些表中被实例化,而抽象类Person则没有对丿卫的表。分 别为每张表分配了对应的主键,customerPOID和employeeP0IDo为j"支持后加 的类Executive,

33、需要做的全部事情就是添加一张相应的表,表中包括所有 Executive对象所需要的属性。图9.把具体类映射成表詞江纟I 翻译UlliA: wwwiedsapmcom-#-詞江纟I 翻译UlliA: wwwiedsapmcom-#-CustomerCustomerPOID «PK»NamePreferencesEmployeeEmployeePOID «PK» NameSalaryCustomerCustomerPOID «PK» HamePreference®EmployeeEmployeePOID «PK

34、7; NameSalary詞江纟I 翻译UlliA: wwwiedsapmcom-#-詞江纟I 翻译UlliA: wwwiedsapmcom-#-ExecutiveExecirtivePOID «PK» NameSalaryBonus3每个类单独映射到一张表 詞江纟I 翻译UlliA: wwwiedsapmcom-#-遵循这个策略,为每个类创建一张表,每个业务属性和任何必须的标识信息都对 应丁表中的一个字段(还包括并发控制和版本跟踪所需的其他字段)。将每个类 都映射成一张单独的表,图6中的类层次结构对应的物理数据模型如图10所示。 类Ousro加z的数据被”储在两张表Cus

35、tomer和Person rb,因此要获取这吐数 据,你需要连接这两张表(或者分两次读取,每张表读一次)。键的应用很有意思。注意per。/沪0是如何作为所有表的主键來使用的。对丁 Customer, Employee, 和 Executive 这些表而言,personPOI摘谨¥.键乂是 外键。对Customer, personPOlD它的主键,同时也作为外键來维系与表 Perso刀之间的关联。这是用戸1<>>和<FK»W种衍型(stereotype)來表示的。 在一些较早版本的UML中,不允许为单个模型元素赋多个衍型(stereotype), 但在

36、UML1.4版中,取消了这一限制。图10.每个类单独映射一张表通常你可能会考虑的修改,是往表Person中添加一个类型字段或苕如尔字段, 用來表示person的可用子类。这个额外的花销将使一些査询变的更容易。在很 多情况下,添加额外的视图(view)也是可行的选择,我更倾向丁这种方法,因 为与附加类型或布尔字段相比,这更易于维护。3.4将类映射为一个通用的表结构将继承结构映射到关系数据库中公的第四种选择是采用一种通用的,有时被称为 元数据驱动(meta-data driven)的方法來映射你的类,这种方法并不局限丁继 承结构,它支持所有形式的映射。图11中所示的,是用于存储屈性值和遍历继 承结

37、构的数据schema。这个schema并不完全,例如它还可以被扩展,用來映射 关联关系,但对丁我们的目的而言是足够用了。单个属性的值"放任怡/3表中, 因此,如果耍保存一个带有十个业务属性的对象,那么需耍十条记录,每个属性 对应一条记录。字段Value. ObjectPOID用來存储特定对象的唯一标识(这种方法 假定对所有对彖采用统的键生成策略,假若不是这样的话,你必须适当的扩展 这个表。)表At tri but eType包含了代表基本数据类型的记录,如数据,字符宙, 钱款,胳数等等。将对象的属性值转换成为Varchar类型保存到Value. Value 字段中时,会需耍这一信息。

38、图11. 一个用于存储对象的通用数据schema让我们一起來看一个例子:将单个类映射到这种schema中。若耍存储图3中的类 Order Item ,表Valued要有三条记录,一条存储己订购的订单项的数目,一条 存储OrderPOIDi 该订单项是相应订单的一部分,还有一条ItemPOID的 值,这个值用來描述订单项。如果你采用乐观锁的方法进行并发控制,你也可以 考虑用第I丿q条记录來储tUpda ted送个shadowJ/4性。表67ass将为类 Orderitem创建一行记录,表Attribute,数据库中为每个属性创建一行记录 (在本例子中,有三行或四行记录)现在,将图6所小的Pers

39、on和Customer之间的继承结构映射到这种schema屮" 衣J7?力MfTMce是继承映射的关键。每个类将山农Class 'I1的一彳j:來农示。在表 Inheri tance 中也有一行,Inheri tance. SuperCiassPOID 的值指向表 Class 中表 示类Person的彳亍,Inheritance. SubClassPOID的值指向表中表示类Customer 的行。映射剩余的结构层次关系,需要在Inheritance表中为每个继承关系都添 加一行。3.5多重继承映射到冃前为止,我所关注的是单根继承层次结构的话题,所谓的单根继承是指,子 类,如C

40、ustomer , K接继承单一的父类,如Person。多重继承是指一个子类 有两个或两个以上的直接父类,如图12所示,Dragon 接继承了类刃加和 Lizard o在面向对象语言中,多重继承通常被认为是有问题的,自1990年以來, 我只见过在一个领域问题中使用多重继承是有意义的,因此,多数语言不支持多 巫继承。但是像C+和Eiffel 样的语言支持多亜继承,所以也存在需要将多 重继承层次结构映射到关系数据库中去的情况。詢江纟|翻译团队:vwwiedsa购com-15 -图12展小的是,对多重继承分别使用三种继承映射策略而得到的结果数据 schemao如图所示,多巫继承映射也是很简单的,跟单

41、根继承映射和比,并没有 任何特别的东西。我所经历的最大挑战是,当将整个层次结构映射到同一张表中 时,如何为这张表取一个合理的名字,在本例中,用併加rme最合适。图12映射多重继承Class ModelPossible Physical Data ModelsCreatureCreaturePOID «PK» NameFireCpacrty MaximumspeedWfngSpanNumber OfClaws ScaleColors满江红翎译团6人:vwwiedsa皿com#满江红翎译团6人:vwwiedsa皿com#BirdLizardmaximumSpeed wingSp

42、annumbe rOfCI a ws scaleColorsBirdBirdPOID «PK» Maximumspeed WingSpanDragonname lireCapacityLizardLizardPOID «PK»MumberOfClawsScaleColorsDragonDragonPOID «PK» Name FireCapacity MaximumSpe e d WingSpan Number Of Claws ScaleColors满江红翎译团6人:vwwiedsa皿com#满江红翎译团6人:vwwiedsa皿co

43、m#3.6映射策略之间的比较如表1所示,就这些策略而言,没有一种策略对所有场合都是理想的。我的经验 表明,最容易奏效的策略是,先用每个层次结构映射一张表的策略,接卜來如果 需耍,就巫构相应的schemao有时,当我的团队被“纯设计方法”的工作方式 所驱动,我会先采用每个类映射一张表的策略。我尽最不使用每个具体类映射一 张表的策略,因为这样做最后导致的典型结果是,需耍把数据在表之间拷來拷去 的,这就强制我在项冃的初期就要对它进行合理重构。我很少使用通用schema 方法,很简单,因为它不具有很好的可伸缩型。在任何应用程序中,你都可以联合使用前三个映射策略:每个层次结构一个张表. 每个具体类一张表

44、和每个类一張表,理解这一点很巫要。你共至可以在一个大型 的层次结构中联合使用这三种策略。表1继承映射策略的比较Stmtegy策略Advantages 优势Disadvantages峡陷When to Use 使用的时机每个层次结构一张表方法简单。添加新类很方便,你只需 耍为新加的数据添加新 的字段即可。通过简单的修改行的“类 型”字段来实现多态。因为数据在一张表中,因 此数据的访问速度很快。因为所冇的数据在同一 张表中,特别容易生成专 门的报表。因为所有的类直接关联到 同一张农,类层次结构内的 耦合度增加。修改一个类将 影响整张表,而整张表的改 变又会影响类层次结构中 的其他类。数据库空间存在

45、潜在浪费。如果已有类型之间有较大 的贞舍,则暗示着类教复杂 化了。对人的层次结构而言,表会 非常人。对那些类层次结构 内部的类型间不存 在或存在极少重叠 情况的简单类层次 结构和(或)继承深 度比较浅的类层次 结构而言,这种策略 很好每个具体类 一张表由j:单个类的所有数据 都存储在一张表中,所以 特别容易生成专门的报 表。访问单个对象数据的性 能高。类修改的时候必须修改它 对应的表,同时也必须修改 它所冇的子类対应的表。举 例来说,如果你给类Person 添加 了 height 和 weight 两 个属性,那么你需要给表 Customer. Employee 和 Executive添加对应

46、的字段。当一个对象改变了它的角 色,比如,你雇用了你的顾 客,你需要把对象的数据复 制到相应的农中,并为它分 配一个新的POID值(或者 可以重用已有的POID值)。很难既支持多角色又能保 持数据的完整性。比如,你 把既是顾冬乂是雇员的人 的名字存放到哪里?肖类型很少改变,类 型之间极少重叠时, 可以选择使用这种 策略。每个类一张因为是一一对应的映射,每个类张表,则在数据库在类熨之间冇较人满江红翎译团6人:vwwiedsa皿com17所以容易理解。侮个类型的记录分别在 相应的表中,因此可以很 好的支持多态。修改父类,或添加新的子 类时,只需要简单的修改 或添加一张表。数据的人小跟対象个数 的增

47、长成正比。中有很多表(还需要附加表 用來维护类Z间的关系)。使用这种方法,使得读写数 据需要更长的时间,因为需 要访问多张表。如采你明智 的组织你的数据库,把_个 类层次结构中的毎张表放 入不同的物理驱动盘盘面 上(假设驱动器磁头的所仃 操作相互独立),就可以提 高数据的读写速度。从数据库生成专门的报表 特别困难,除非添加视图来 模拟所需耍的表。豆叠,或类型会频繁 的修改的情况卜使 用这种策略。通川schema当用一个稳定的持久化 框架來寸装数据库的访 问,可以工作的非常好。可以扩展到提供元数据, 以支持包括关系映射在 内的更大范围的映射。简 而言之,它是元数据映射 引擎的起点。非常灵活,可以

48、快速的改 变存储对象的方式,因为 只需嗖更新存储在表 Class > Inheritance » Attribute 和 AttributeType 中的元数据。很先进的技术最初可能难 以实现。使用这种方法,需要访问很 多数据库的记录來创建一 个对彖,因此它只适用少 最数据的情况。你可能需要一个小型的管 理程序來维护元数据。内为耍访问多行记录來获 取一个对象的数据,因此, 用这种数据生成报表显得 异常困难。适用r如卜场介:处理少彊数据的复 杂应用程序:不常访问数据的应 用程序:町以预先将数据读 入到缓存的应用程 序。3. 映射对象关系除了属性映射与继承映射,你还需要领会关系映射的艺术。有三种你需耍进行映 射的对象间关系:关联、聚合以及组合。在这电,我将把这三种关系同等看待一 尽管涉及到引用完整性的时候,三者有些微

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 社会民生


经营许可证编号:宁ICP备18001539号-1