對象-關(guān)系數(shù)據(jù)庫之間的映射_第1頁
對象-關(guān)系數(shù)據(jù)庫之間的映射_第2頁
對象-關(guān)系數(shù)據(jù)庫之間的映射_第3頁
對象-關(guān)系數(shù)據(jù)庫之間的映射_第4頁
對象-關(guān)系數(shù)據(jù)庫之間的映射_第5頁
已閱讀5頁,還剩18頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、目錄1.1.11.21.31.3.1 映射對象 . 1 屬性類型映射成域 . 1 屬性映射成字段 . 2 類映射成表 . 2 關(guān)系數(shù)據(jù)庫中實(shí)現(xiàn)繼承 . 21.41.4.11.4.2 關(guān)系映射 . 4 關(guān)聯(lián)與聚集/組合之間的區(qū)別 . 4 關(guān)系數(shù)據(jù)庫中實(shí)現(xiàn)關(guān)系 . 5 2.2.12.22.33.3.13.23.3 引用完整性及關(guān)系約束檢查. 7 對象之間的關(guān)系和父表操作的約束。 . 7 子表操作的約束 . 10 小結(jié) . 10 對象標(biāo)識符(OBJECT ID) . 11 OID不應(yīng)具有商業(yè)意義。 . 11 OID的唯一性 . 11 分配OID的策略 . 12在整數(shù)列上使用MAX() . 12使用并

2、維護(hù)鍵值表 . 12GUID/UUID . 12使用Persistence 機(jī)制提供的功能 . 12 HIGH/LOW方法 . 12 3.3.1 3.3.2 3.3.3 3.3.4 3.3.54.4.14.24.35.5.15.25.35.45.55.65.75.85.95.106. 關(guān)系數(shù)據(jù)庫常用技術(shù) . 15 索引(Indices) . 15 存儲過程(Stored Procedures) . 15 觸發(fā)器(Triggers) . 16 對象關(guān)系數(shù)據(jù)庫映射的討論 . 17 對象設(shè)計(jì)和關(guān)系數(shù)據(jù)庫是常用實(shí)現(xiàn)標(biāo)準(zhǔn) . 17 ODBC和JDBC的類是不夠的 . 17 因而,需要Persistenc

3、e層設(shè)計(jì) . 17 硬編碼的SQL語句是很糟糕的主意 . 18 必須映射到現(xiàn)存的數(shù)據(jù)庫 . 18 數(shù)據(jù)模型不應(yīng)驅(qū)動類設(shè)計(jì) . 18 表連接速度很慢 . 18 避免使用帶商業(yè)意義的主鍵 . 18 合成主鍵也如此 . 18 存儲過程是一種很蹩腳的方法 . 19 術(shù)語 . 20- I -對象-關(guān)系數(shù)據(jù)庫之間的映射面向?qū)ο笤O(shè)計(jì)的機(jī)制與關(guān)系模型的不同,造成了面向?qū)ο笤O(shè)計(jì)與關(guān)系數(shù)據(jù)庫設(shè)計(jì)之間的不匹配。面向?qū)ο笤O(shè)計(jì)基于如耦合、聚合、封裝等理論,而關(guān)系模型基于數(shù)學(xué)原理。不同的理論基礎(chǔ)導(dǎo)致了不同的優(yōu)缺點(diǎn)。對象模型側(cè)重于使用包含數(shù)據(jù)和行為的對象來構(gòu)建應(yīng)用程序;關(guān)系模型則主要針對于數(shù)據(jù)的存儲。當(dāng)為訪問數(shù)據(jù)尋找一種合

4、適的方法時(shí),這種不匹配就成為了主要矛盾:使用對象模型,常常通過對象之間的關(guān)系來進(jìn)行訪問;而根據(jù)關(guān)系理論,則通過表的連接、行列的復(fù)制來實(shí)施數(shù)據(jù)的存取。這種基本的不同使兩種機(jī)制的結(jié)合并不理想。換言之,需要一種映射 方法來解決該矛盾,從而獲得成功的設(shè)計(jì)。1. 映射對象 屬性類型映射成域 屬性映射成列 類映射成表。 o 在關(guān)系數(shù)據(jù)庫中實(shí)現(xiàn)繼承。 映射關(guān)系。 o 1對1。 o 1對多。 o 多對多。 o 關(guān)聯(lián)與依賴。 o 相同的類/表,不同的關(guān)系。1.1 屬性類型映射成域UML中的屬性類型(Attribute Type)映射成數(shù)據(jù)庫中的域(Domain)。域的使用提高了設(shè)計(jì)的一致性,且優(yōu)化了應(yīng)用的移植性

5、。簡單的域是非常容易實(shí)現(xiàn)的,僅僅需要替換相對應(yīng)的數(shù)據(jù)類型和數(shù)據(jù)的尺寸。同時(shí),對于使用域的屬性,可能要求為域的約束加入SQL的Check串。例如,限定域的取值范圍等。枚舉域(Enumeration Domain)限定了域允許取值的集合。枚舉域較簡單域?qū)崿F(xiàn)更復(fù)雜。下表對各種實(shí)現(xiàn)方法進(jìn)行了比較。- 1 -1.2 屬性映射成字段類的屬性映射至關(guān)系數(shù)據(jù)庫中0個(gè)或多個(gè)字段。并不是類中的所有屬性均是永久的。例如,發(fā)票(Invoice)中的合計(jì)(grandTotal)屬性可能是用于計(jì)算而不需保存在數(shù)據(jù)庫中。另外,有時(shí)某個(gè)對象包含其它對象,如顧客(Customer)中的Address屬性(Address本身映射

6、為數(shù)據(jù)庫表)。此時(shí),屬性映射成多個(gè)字段。1.3 類映射成表類直接或間接的映射成表。除非是非常簡單的應(yīng)用,類與表之間才會存在一一對應(yīng)的關(guān)系。在本節(jié)中列舉三種策略來在關(guān)系數(shù)據(jù)庫中實(shí)現(xiàn)繼承。1.3.1 關(guān)系數(shù)據(jù)庫中實(shí)現(xiàn)繼承在關(guān)系數(shù)據(jù)庫中,一個(gè)關(guān)鍵問題是表主鍵的唯一性策略的選取。適當(dāng)?shù)姆桨改軆?yōu)化繼承、組合及對象之間關(guān)系的實(shí)現(xiàn)。進(jìn)一步的討論參見對象標(biāo)識符(OID)??紤]類的繼承問題。在關(guān)系數(shù)據(jù)庫中保存對象時(shí),基本上問題歸結(jié)于“組織被繼承的屬性?”該問題的不同解決方案會影響到整個(gè)設(shè)計(jì)。圖1給出了簡單的類層次例子。圖1:類層次UML示意圖關(guān)系數(shù)據(jù)庫中實(shí)現(xiàn)繼承的方法可劃分為三類:1. 將整個(gè)類層次映射為單個(gè)數(shù)

7、據(jù)庫表。- 2 -類層次的所有類映射為單個(gè)的數(shù)據(jù)庫表,表中保存所有類(基類、子類)的屬性。圖1層次模型該方法的實(shí)現(xiàn)如下圖所示:圖2:類層次映射至單個(gè)表優(yōu)點(diǎn):實(shí)現(xiàn)簡單。支持多態(tài)對象角色發(fā)生變化,或存在多重角色時(shí)。報(bào)表操作實(shí)現(xiàn)簡單:表中包含了所有信息。缺點(diǎn):增加類層次中的耦合。類層次中任何類的屬性的增加會導(dǎo)致表的變更;如果在某個(gè)子類屬性的修改錯(cuò)誤會影響到整個(gè)層次結(jié)構(gòu),而不僅僅是該子類。浪費(fèi)了大量的數(shù)據(jù)庫空間。可能需要指明具體的角色。2. 每個(gè)具體子類映射成單個(gè)數(shù)據(jù)庫表。數(shù)據(jù)庫表包括自身的屬性和繼承的屬性,每個(gè)具體的子類包含各自的OID。抽象的基類不參與映射。圖3描述了該方法的實(shí)現(xiàn)。其中,Perso

8、n由于是抽象類,未映射成數(shù)據(jù)庫表;而Student、Professor類映射為相應(yīng)的表,它們具有各自的主鍵。圖3:具體類映射成數(shù)據(jù)庫表優(yōu)點(diǎn):報(bào)表操作實(shí)現(xiàn)簡單:表中包含了具體子類的所有信息。缺點(diǎn):類的修改會導(dǎo)致相對應(yīng)的表及其子類所對應(yīng)表的更改。角色的更改會造成ID的重新賦值(因?yàn)椴煌宇惖腎D可能重復(fù))。難以在支持多重角色時(shí),保持?jǐn)?shù)據(jù)的完整性。3. 每個(gè)類均映射為數(shù)據(jù)庫表。- 3 -為每一個(gè)類創(chuàng)建數(shù)據(jù)庫表,表中包含特定于該類的屬性和OID。圖4顯示了該方法,注意personOID作為所有表的主鍵,它們之間是is-a的關(guān)系。圖4:每個(gè)類均映射為數(shù)據(jù)庫表優(yōu)點(diǎn):與面向?qū)ο蟮母拍畹囊恢滦宰詈谩Χ鄳B(tài)的支

9、持最好,對于對象所可能的充當(dāng)?shù)慕巧珒H需要在相應(yīng)的表中保存記錄。 易于修改基類和增加新的類。缺點(diǎn):數(shù)據(jù)庫中存在大量的表。 訪問數(shù)據(jù)的時(shí)間較長。對報(bào)表的支持較差,除非定義視圖。以上三種方法各有優(yōu)缺點(diǎn),沒有一種是完美的。下表對它們提供對比。1.4 關(guān)系映射不僅僅是對象需要被映射至數(shù)據(jù)庫,對象之間的關(guān)系也需要映射至數(shù)據(jù)庫。對象之間的關(guān)系可分為:繼承(Inheritance),關(guān)聯(lián)(association),聚集(aggregation),組合(composition)。欲有效地映射關(guān)系,必須理解它們之間的不同點(diǎn),如何實(shí)現(xiàn)一般的關(guān)系以及如何實(shí)現(xiàn)特定的多對多關(guān)系。1.4.1 關(guān)聯(lián)與聚集/組合之間的區(qū)別從數(shù)

10、據(jù)庫的角度,關(guān)聯(lián)與聚集/組合之間的區(qū)別在于對象間的耦合程度。對于聚集/組合,在數(shù)據(jù)庫中對整體的操作時(shí)通常需要同時(shí)對部分進(jìn)行操作,而關(guān)聯(lián)則不然。圖5中有3個(gè)類,其中Airport與Airplane之間是簡單的關(guān)聯(lián)關(guān)系,而Airplane與Wing之間是聚集/組合關(guān)系。從數(shù)據(jù)庫的觀點(diǎn)來說,聚集/組合關(guān)系往往在訪問整體Airplane時(shí),- 4 -往往需要訪問Wing,而對于Airport與Airplane,這種關(guān)系并不是十分明顯。相應(yīng)的,在保存/刪除對象時(shí),也存在類似的情況。當(dāng)然,以上討論的特定于商業(yè)規(guī)則,但該經(jīng)驗(yàn)之談往往在很多情況下出現(xiàn)。圖5:關(guān)聯(lián)與聚集/組合之間的區(qū)別1.4.2 關(guān)系數(shù)據(jù)庫中實(shí)

11、現(xiàn)關(guān)系關(guān)系數(shù)據(jù)庫中通過使用外鍵來實(shí)現(xiàn)關(guān)系。外鍵允許將表中的某一行與其它表中的行相關(guān)聯(lián)。實(shí)現(xiàn)一對一或一對多關(guān)系,僅僅需要在表中加入另一個(gè)表的主鍵。 可選的1對強(qiáng)制的1將外鍵放臵在可選的一端,該外鍵不能為空值。例如,某公司員工使用電腦的情況,要求員工最多能使用一臺電腦,且電腦資源應(yīng)充分的利用。圖6中,Computer中放臵外鍵。圖6:可選1對強(qiáng)制1關(guān)系的實(shí)現(xiàn)其它1對1的情況外鍵可放臵在任意一邊,具體情況依賴于性能等因素。例子如圖7。注:對于1對1的情況,不要在兩個(gè)表中均放臵對方的主鍵。這樣,增加了冗余,且并不會提高性能。對于強(qiáng)制性,一般在商業(yè)規(guī)則的對應(yīng)層實(shí)現(xiàn),而不在Persistent Layer

12、中實(shí)現(xiàn)。 圖7:1對1關(guān)系的實(shí)現(xiàn)1對多的情況將外鍵放臵在“多”的一方。外鍵的空/非空由對1的強(qiáng)制性決定。示意圖如圖8。- 5 -圖8:1對多關(guān)系的實(shí)現(xiàn)多對多的情況實(shí)現(xiàn)多對多關(guān)系,需要引入關(guān)聯(lián)表(associative table)的概念。(參見術(shù)語)在圖9中,Customer和Account之間存在多對多的關(guān)系。圖10顯示了如何在關(guān)系數(shù)據(jù)庫中實(shí)現(xiàn)多對多的關(guān)系。圖9:多對多關(guān)系的類傳統(tǒng)實(shí)現(xiàn)中,關(guān)聯(lián)表的屬性包含關(guān)系中兩個(gè)表的主鍵,并且關(guān)聯(lián)表的主鍵往往是它們的組合。另一種實(shí)現(xiàn)方法是將關(guān)聯(lián)表視為普通表,使用自身的主鍵OID,然后加入實(shí)現(xiàn)關(guān)系所必需的外鍵,如圖10所示。圖10:關(guān)系數(shù)據(jù)庫中多對多關(guān)系的實(shí)

13、現(xiàn)該方法的好處在于Persistent Layer中,所有的表具有相同的形式,簡化了實(shí)現(xiàn);另外,提高了運(yùn)行時(shí)效率:一些數(shù)據(jù)庫在連接具有復(fù)合外鍵的表時(shí),性能較差;并且,存在著向Accesses表中增添字段的可能,如:需要增加對帳戶訪問安全性檢查,可能某個(gè)帳戶只允許取千,而另一個(gè)帳戶擁有所有的權(quán)限。- 6 -2. 引用完整性及關(guān)系約束檢查在UML中,對象之間的關(guān)系通常指關(guān)聯(lián)、聚集、組合。其中,聚集時(shí)更加嚴(yán)格意義上的關(guān)聯(lián);而組合則是更加嚴(yán)格的聚集。對象之間的關(guān)系反映了具體的商業(yè)規(guī)則,因此將對象映射到關(guān)系數(shù)據(jù)庫時(shí),必須保證對象之間的關(guān)系定義并確保數(shù)據(jù)庫上數(shù)據(jù)的約束。 在采用了對象標(biāo)識符(OID)中OI

14、D的策略時(shí)(即所有的對象具有唯一的ID,相應(yīng)的數(shù)據(jù)庫中所有表的主鍵均具有唯一性;OID不具有商業(yè)內(nèi)涵),則在數(shù)據(jù)庫級發(fā)生更新時(shí),不會出現(xiàn)完整性問題,但就對象交互及滿足商業(yè)規(guī)則而言,對約束的普遍討論具有一定的意義。以下就1對多的情況考慮限制檢查。(1對1關(guān)系可以視為特殊的1對多關(guān)系;多對多關(guān)系則可以分解為兩個(gè)1對多關(guān)系)2.1 對象之間的關(guān)系和父表操作的約束。關(guān)聯(lián)關(guān)聯(lián)是一種較弱的關(guān)系。體現(xiàn)了實(shí)體間的聯(lián)系。關(guān)系較松散,可能不需要映射,具體表現(xiàn)為不需要保存對方的引用,而僅僅在方法上有交互;如果在數(shù)據(jù)上有耦合關(guān)系時(shí),可能需要映射。圖11:可選對可選(O-O)約束 圖12:強(qiáng)制對可選(M-O)約束在Pr

15、ofessor與Student的關(guān)系中,存在M-O約束(Mandatory-Optional),映射示意圖如下:圖13:強(qiáng)制對可選(M-O)約束的實(shí)現(xiàn)父表操作的約束:父表的Insert操作,對M-O約束,父表中間的記錄可以沒有任何約束地添加到表中,因?yàn)檫@種約束中父親不一定必須有子女。父表的鍵值修改操作,只有在子表中其所有地子女地對應(yīng)值均做修改后,才能修改。即一般采用級聯(lián)更新的方法。即:1. 插入新的父記錄,將子表中原對應(yīng)記錄外鍵更新,刪除原父記錄。對該操作進(jìn)行封裝。2. 采用數(shù)據(jù)庫提供的級聯(lián)更新的方法。父表的刪除,父親只有在其所有子女均被刪除或重新分配之后該父親才能被刪除。在Professor

16、-Student關(guān)系中,所有學(xué)生可以重新分配。對應(yīng)的實(shí)現(xiàn):1. 先刪除子記錄,再刪除父記錄。- 7 -2.3.先行將子記錄的外鍵更改,再刪除父記錄。 采用數(shù)據(jù)庫提供的級聯(lián)刪除操作。在Project與Employee的關(guān)聯(lián)中,存在O-O約束(Optional-Optional)。映射圖如下: 圖14:可選對可選(O-O)約束的實(shí)現(xiàn)父表操作的約束:理論上,在具有這種關(guān)系的約束中,任何類型的修改都沒有限制。Project和Employee中的行可以按需要而進(jìn)行修改。具體的處理方法與聚集相同。聚集關(guān)聯(lián)的一種特殊形式,指定了整體(Whole、Aggregate)與部分(Part、Component)之間

17、的關(guān)系。如圖15中,俱樂部與學(xué)生之間的關(guān)系。圖15:聚集類型示薏聚集一般映射成為如圖16所示的結(jié)構(gòu),注意在子表Student中外鍵可以為空。該約束為O-M(Optional-Mandatory)形式。圖16:聚集關(guān)系的映射實(shí)現(xiàn),O-M約束父表操作的約束:父表的Insert操作,對O-M約束,一個(gè)父親只有當(dāng)至少當(dāng)它的一個(gè)子女同時(shí)被加入,或至少已經(jīng)存在一個(gè)合法的子女時(shí),才能被加入。例如,圖16中的Club和Student之間的關(guān)系,一個(gè)新的Club只有當(dāng)已經(jīng)有學(xué)生時(shí)才能被加入(或者該學(xué)生已經(jīng)存在或者可以創(chuàng)建一個(gè)學(xué)生,或者修改一個(gè)學(xué)生所在俱樂部的值),總之必須要已經(jīng)有適當(dāng)?shù)膶W(xué)生存在。具體的操作:1.

18、 可以先行加入主表記錄,再修改子表的外鍵。2. 同時(shí)加入主表、子表記錄(次序無關(guān)),再更新子表的外鍵。注:如果先加入子表記錄時(shí),可能在關(guān)系數(shù)據(jù)庫中無法保存加入子記錄的數(shù)據(jù)集。其商業(yè)規(guī)則更傾向于對已有子對象的組合。父表的鍵值修改操作,只有當(dāng)一個(gè)子女被創(chuàng)建或已經(jīng)有一名子女存在才行。也就是說只有當(dāng)至少一名滑雪者愿意參加Scuba俱樂部或者已經(jīng)有一名學(xué)生參加Scuba俱樂部時(shí),SKI Club才可以改名為Scuba俱樂部。針對于實(shí)現(xiàn)而言:1. 在修改的同時(shí)將子表外鍵臵空。2. 子表需要級聯(lián)修改。- 8 -父表的刪除,理論上刪除父親是沒有限制的。實(shí)際上,刪除主表記錄時(shí),不采用級聯(lián)刪除子表的方案,而采用將

19、子表的外鍵臵空。該方法與聚集的語義是相一致的。組合組合指具有強(qiáng)主從關(guān)系和一致性的一種聚集關(guān)系。在合成對象創(chuàng)建之后,可能創(chuàng)建多個(gè)成員。成員一旦創(chuàng)建,就與合成對象具有相同的生命周期。成員可以在合成對象終止之前顯式的刪除。組合可以是遞歸的。如旅館帳單與帳單上條目的關(guān)系。 圖17:組合關(guān)系示薏組合的映射示意圖見圖18,其中子表DailyCharge中的外鍵InvoiceNumber為強(qiáng)制性的。更嚴(yán)格的說來,它們之間的約束應(yīng)為M-M約束(Mandatory-Mandatory)。圖16:組合關(guān)系的映射實(shí)現(xiàn),M-M約束父表操作的約束:父表的Insert操作,可能隨后需要生成子女,即在子表中創(chuàng)建新的行。也可

20、能通過對子表的重新分配來實(shí)施完整性限制,如插入InvoiceNumber = 2的記錄,接著將DailyCharge表中原外鍵為5的修改至2。即將Insert操作封裝為原子操作。但根據(jù)組合的語義,上述情況更適合使用聚集來描述。父表的鍵值修改操作,只有在子表對應(yīng)的外鍵的值修改成新值時(shí)才能執(zhí)行。根據(jù)組合的定義,更有可能是先創(chuàng)建新的父表記錄,接著修改子表所有原對應(yīng)的記錄,使其與父表的新記錄關(guān)聯(lián),最后刪除原父表記錄。父表的刪除,只有在子表中所有相關(guān)的行全部刪除或重新分配之后,才能刪除父表中的記錄。同樣,根據(jù)組合的定義,一般對子表進(jìn)行刪除操作。父表上操作小結(jié):- 9 -2.2 子表操作的約束施加子表的約

21、束主要是為了防止碎片的產(chǎn)生。一個(gè)明顯的區(qū)別是,在一些情況下,一個(gè)子女(子表中的記錄)只有在當(dāng)其兄弟存在時(shí)才能被刪除或修改。如在O-M、M-M約束中,即最后一個(gè)存在的子女是不能被刪除或修改的。此時(shí),可以對父記錄進(jìn)行即時(shí)的更新?;蛘呓乖摬僮鳌6颖砑s束的實(shí)現(xiàn),可以通過在數(shù)據(jù)庫中加入觸發(fā)器;更合理、可行的方法是將子表一方的限制,在業(yè)務(wù)層中實(shí)現(xiàn)。子表上操作小結(jié):以上的討論是從關(guān)系數(shù)據(jù)庫的角度出發(fā),但在對象的處理中仍具有意義。在對對象進(jìn)行增、刪、改操作時(shí),與之對應(yīng)的數(shù)據(jù)庫記錄的操作應(yīng)同它相對應(yīng)。關(guān)系數(shù)據(jù)庫基于關(guān)系數(shù)學(xué)、函數(shù)依賴等特性,無法充分的體現(xiàn)對象之間的關(guān)系和限制。所以,即使使用數(shù)據(jù)庫來強(qiáng)制各種約

22、束,也不一定能保證滿足商業(yè)規(guī)則的需要。其次,數(shù)據(jù)庫的某些約束與其生產(chǎn)廠商、版本相關(guān),不利于進(jìn)行移植。2.3 小結(jié)ID的選?。翰捎弥械腛ID策略。由于對象標(biāo)識OID同時(shí)作為表的主鍵,并且不具有商業(yè)意義。因此,可以避免在數(shù)據(jù)庫操作時(shí)的很多限制,而相應(yīng)的約束的處理由Persistent Layer轉(zhuǎn)移到業(yè)務(wù)層來實(shí)現(xiàn)。數(shù)據(jù)庫表的映射:采用子表外鍵為空的方案映射對象。父表的Insert操作:如果子記錄已經(jīng)存在,則先插入父記錄,在更改子表的外鍵,如將空值更新為父記錄,或者更改外鍵此時(shí),可能需要在業(yè)務(wù)層對子對象(子表)的完整性進(jìn)行判斷。如果子記錄不存在,則先插入父記錄,然后根據(jù)父記錄的主鍵直接構(gòu)造子記錄。父

23、表的Update操作:如果更新的父記錄不存在,則先插入父記錄,更新子表,刪除原有的父記錄。反之,直接修改子表記錄,刪除原有的父記錄。父表的Delete操作:先刪除子表記錄或?qū)⑵渫怄I更改(臵空或修改),刪除父記錄。 子表的操作:子表的操作在業(yè)務(wù)層中實(shí)現(xiàn)。 盡量避免使用存儲過程或者觸發(fā)器。 應(yīng)用程序在執(zhí)行數(shù)據(jù)約束時(shí)有很重要的作用。在四類約束:M-M、M-O、O-M、O-O。鍵值的修改可能會改變表之間的關(guān)系,而且可能違反一些約束。違反約束的操作是不允許的。而前面的規(guī)則僅為具體實(shí)現(xiàn)提供了可能性。具體的應(yīng)用必須根據(jù)實(shí)際的要求和商業(yè)規(guī)則進(jìn)行適當(dāng)?shù)倪x擇。但在設(shè)計(jì)和開發(fā)時(shí),必須考慮所分析的約束。- 10 -3

24、. 對象標(biāo)識符(Object ID)針對于對象,需要能夠唯一識別它們的標(biāo)識符。在關(guān)系數(shù)據(jù)庫中,對應(yīng)的概念稱之為鍵(Key);在面向?qū)ο蟮募夹g(shù)中,稱之為OID(Object ID)。OID在對象模型中的典型實(shí)現(xiàn)是作為完整的對象,而在關(guān)系模型中,則作為整數(shù)來實(shí)現(xiàn),或者對于較大的應(yīng)用中,以若干整數(shù)來實(shí)現(xiàn)。OID用來在關(guān)系數(shù)據(jù)庫中唯一的標(biāo)識對象。圖18描述了OID類的可能實(shí)現(xiàn),圖19則顯示了映射機(jī)制。OID簡化了關(guān)系數(shù)據(jù)庫的主鍵方案。盡管OID并未完全解決對象間的瀏覽問題,但是它確實(shí)簡化了操作。假設(shè)你不愿使用遍歷的方法來讀取聚集對象的成員,例如:發(fā)票與發(fā)票中的條目,則仍可以使用表關(guān)聯(lián)來實(shí)現(xiàn),至少提供了

25、實(shí)現(xiàn)的可能。使用OID的另一個(gè)好處是使開發(fā)處于易于維護(hù)對象間關(guān)系的位臵。當(dāng)所有表的主鍵采用相同的類型的列來實(shí)現(xiàn)時(shí),非常容易編寫使用該特性的通用代碼。3.1 OID不應(yīng)具有商業(yè)意義。OID在任何情況下,都不應(yīng)包含商業(yè)內(nèi)涵。存在商業(yè)意義的任何列都有潛在變化的可能。而在關(guān)系數(shù)據(jù)庫中,采用有意義的主鍵是致命的錯(cuò)誤。如果用戶決定改變字段的商業(yè)含義,則需要在所有使用到該信息的地方進(jìn)行修改。主鍵的作用應(yīng)是保持唯一性和作為外鍵使用。任何對主鍵的修改會導(dǎo)致巨大的數(shù)據(jù)庫維護(hù)工作量,顯然這是不合適宜的設(shè)計(jì)。就關(guān)系數(shù)據(jù)庫而言,OID策略采用的是代理主鍵的方法。3.2 OID的唯一性在分配對象標(biāo)識符(OID)時(shí),需要考

26、慮兩個(gè)主要的問題:OID唯一性的級別和如何計(jì)算它們。OID唯一性級別的問題對于面向?qū)ο蟮某跫夐_發(fā)者,并不十分明顯。OID唯一性具有三種級別:具體類中對象標(biāo)識唯一;類層次中對象標(biāo)識唯一;所有類的對象標(biāo)識均唯一。 例如,考慮右圖的類層次模型。假設(shè)對Customer對象給定標(biāo)識OID=74656。則存在以下的可能:1. 該OID可以分配給Employee,因?yàn)镋mployee與Customer是不同的具體類。2. 該OID在類層次中唯一,即不能分配給Employee對象。3. OID在所有類的對象中具有唯一性,從而不能分配該其它任何對象。 圖17:簡單的類層次圖 該問題其實(shí)歸結(jié)于多態(tài)性(Polymo

27、rphism):有可能Customer對象會成為Employee對象。此時(shí),如果采用具體類中的唯一性,為了避免OID與Employee的標(biāo)識的重復(fù),會導(dǎo)致對Customer對象標(biāo)識的重新分配。而為了避免OID的重新分配問題,至少需要類層次中標(biāo)識的唯一性,而所有類中對象標(biāo)識的唯一性可以徹底地解決該問題。OID至少在類層次中應(yīng)具有唯一性,最理想的方案是所有對象標(biāo)識具有唯一性。- 11 -3.3 分配OID的策略第二個(gè)問題,是如何決定新的OID,該問題對應(yīng)用程序運(yùn)行的效率有極大的影響。3.3.1 在整數(shù)列上使用MAX()在整數(shù)列上使用MAX()函數(shù)是一種常用的方法。該方法的基本思想:數(shù)據(jù)庫中插入新行

28、時(shí),在主鍵列上使用MAX()函數(shù)取最大值,加1作為主鍵的新值。該方法的問題是需要在訪問時(shí),對列暫時(shí)加鎖,盡管許多數(shù)據(jù)庫對該操作進(jìn)行了優(yōu)化。 僅在每個(gè)表中的對象取得了唯一的對象OID,并未在所有對象之間保證唯一性。3.3.2 使用并維護(hù)鍵值表該策略有兩種方法。保存并維護(hù)單字段、單行的數(shù)據(jù)表,用來存儲整數(shù)計(jì)數(shù)。當(dāng)進(jìn)行插入操作時(shí),對其加鎖及增1作為新的OID值。方法的優(yōu)點(diǎn)在于避免了調(diào)用MAX()函數(shù)時(shí)對整個(gè)表的鎖定,同時(shí)保證了所有表主鍵的唯一性。缺點(diǎn)則是進(jìn)行大批量插入操作時(shí),該表會成為性能瓶頸(盡管在內(nèi)存中,可以對該值進(jìn)行緩存)以及有效值很快會被耗盡。 另一種方法是,在系統(tǒng)中使用多行鍵值表,每一行對

29、應(yīng)一個(gè)數(shù)據(jù)庫表。鍵值表具有兩個(gè)字段,一個(gè)指定相應(yīng)的表名,另一個(gè)用于確定具體的取值。與前面的方法一樣,它避免了MAX()函數(shù)對整個(gè)表的鎖定,并且由于為每張表使用了鍵值,闊寬了OID的范圍。然而,它失去了對所有表主鍵唯一性的強(qiáng)制;鍵值表仍然可能成為性能的瓶頸。(盡管可以在內(nèi)存中,對這些值進(jìn)行緩存)3.3.3 GUID/UUID許多年前,Digital使用了一種稱之為UUID的策略。該策略基于哈希計(jì)算機(jī)以太網(wǎng)卡的物理標(biāo)識和當(dāng)前時(shí)間來得到唯一的128位鍵值。而對于無以太網(wǎng)卡的計(jì)算機(jī),則可以通過在線的文件得到標(biāo)識數(shù)字。Microsoft具有類似的GUID策略來得到128位的字符串。兩種方法均能很好的工作

30、,盡管它們具有平臺相關(guān)性。另外,不使用Persistence機(jī)制產(chǎn)生ID,始終是一個(gè)潛在的問題。3.3.4 使用Persistence 機(jī)制提供的功能許多數(shù)據(jù)庫,如Oracle,能自動的產(chǎn)生唯一的序列值。盡管該方案可以很好的工作,但它們采用了廠商私有的方法,且在定義時(shí)確定,從而無法進(jìn)行有效地控制。如果面臨跨平臺移植時(shí),可能成為非常嚴(yán)重的問題。3.3.5 HIGH/LOW方法替代使用較大整數(shù)來獲取OID的方法(要求對單個(gè)資源字段進(jìn)行訪問,從而成為瓶頸):將OID分解為兩個(gè)邏輯組成部分。在應(yīng)用程序首次需要?jiǎng)?chuàng)建OID時(shí),向數(shù)據(jù)庫的單個(gè)字段請求HIGH值(或者從某些數(shù)據(jù)的內(nèi)建函數(shù)獲得),對于LOW值,

31、初始化為0,在本次會話隨后的請求遞增。如果LOW值到達(dá)了極限,則再次向數(shù)據(jù)庫申請HIGH值。由于HIGH值互斥的獲得,進(jìn)而保證了唯一性。- 12 -HIGH/LOW方法的優(yōu)點(diǎn),每次會話只需與數(shù)據(jù)庫交互一次,減少了流量,使鍵值表的訪問不再成為瓶頸。其次,保證了OID在所有對象中的唯一性。與前面所提到的方法比較,HIGH/LOW方法是最有效和實(shí)現(xiàn)較簡易的方法。1. HIGH/LOW方法的實(shí)現(xiàn)采用OO方法實(shí)現(xiàn)OID策略,使用類封裝OID的行為。圖18顯示了實(shí)現(xiàn)OID的一種法方法。其基本思想是在創(chuàng)建永久對象:由ObjectFactory對象(可參見創(chuàng)建設(shè)計(jì)模式中的Singleton)為它分配OID,O

32、bjectFactory的唯一職責(zé)創(chuàng)建新的OID對象。ObjectFactory跟蹤HIGH和LOW的取值來得到新的OID。具體而言,通過訪問Persistence機(jī)制(數(shù)據(jù)庫)來獲取HIGH,而基于LOW的當(dāng)前值返回唯一的OID。asColumns方法則以關(guān)系數(shù)據(jù)庫的存儲的對應(yīng)形式返回OID的實(shí)例。圖18:HIGH/LOW OID的一種可能實(shí)現(xiàn)的類示意圖圖19展示了在關(guān)系數(shù)據(jù)庫中實(shí)現(xiàn)HIGH/LOW OID策略可能的實(shí)現(xiàn)方法。沒有任何一種是完美的,各有優(yōu)缺點(diǎn)。重要的是選擇一種方案,并對數(shù)據(jù)庫中的表一致地實(shí)施,使Persistence層更加容易開發(fā)、維護(hù)。1. 為主鍵定義單個(gè)整數(shù)。該方法設(shè)計(jì)簡

33、單,但OID的取值范圍較小。(0數(shù)據(jù)庫所允許整數(shù)的最大值)2. 使用任意長度字符串作為主鍵避免了上述的問題,但增加了運(yùn)行開銷。(許多數(shù)據(jù)庫對整數(shù)作為主鍵進(jìn)行了優(yōu)化,而對字符串作為主鍵的訪問較慢)3. 采用復(fù)合主鍵較方法2減少了存儲開銷,但仍具有某些弊端,具體討論參見對象關(guān)系數(shù)據(jù)庫映射的討論。4. 結(jié)合方法2、3,對OID對象進(jìn)行哈希操作,將其轉(zhuǎn)換成字符串?;舅枷胧菍ID轉(zhuǎn)化成一系列的8位的數(shù)字,接著根據(jù)數(shù)字構(gòu)造字符,最后將字符連接成字符串。圖19:關(guān)系數(shù)據(jù)庫映射HIGH/LOW OID的可能實(shí)現(xiàn)- 13 -推薦方案:高位(HIGH)采用96位的數(shù)字(通常是3個(gè)32位的整數(shù)),低位(LOW)

34、采用32位的數(shù)字。接著,將其轉(zhuǎn)換成128位的字符串。該方案的最大缺點(diǎn)是許多數(shù)據(jù)庫可能對于定長字符串的主鍵未進(jìn)行優(yōu)化。具體的方法則應(yīng)根據(jù)需求來確定。2. 分布式環(huán)境下的HIGH/LOW方法的實(shí)現(xiàn)如前面所提到的,OID必須唯一。在分布式環(huán)境中,客戶機(jī)從眾多服務(wù)器中取得HIGH值,應(yīng)如何保證該值的唯一性呢?答案很簡單:服務(wù)器之間也必須使用HIGH值唯一的策略。對應(yīng)有許多方案,如:服務(wù)器使用自己的HIGH/LOW方法,而從唯一的資源處獲得HIGH值;或者,服務(wù)器從某個(gè)集中式的服務(wù)得到HIGH值塊,在HIGH值分配完之后重新申請新的塊。3. 多廠商數(shù)據(jù)庫環(huán)境下的HIGH/LOW方法的實(shí)現(xiàn)另一個(gè)相關(guān)的問題

35、是,許多大型機(jī)構(gòu)往往使用多種廠商的數(shù)據(jù)庫來實(shí)現(xiàn)Persisntence層的設(shè)計(jì)。盡管各種廠商都有特定的機(jī)制來產(chǎn)生代理鍵值,即使在分布式的環(huán)境中,但大多都只能應(yīng)用于特定的產(chǎn)品。例如:產(chǎn)品A的機(jī)制產(chǎn)生HIGH值1701,而產(chǎn)品B也產(chǎn)生了1701的HIGH值。從而會導(dǎo)致兩難的局面。此時(shí)要求能將HIGH/LOW實(shí)現(xiàn)的方法應(yīng)用到上述環(huán)境中,可以使用上節(jié)的方法來進(jìn)行處理。- 14 -4. 關(guān)系數(shù)據(jù)庫常用技術(shù)4.1 索引(Indices)實(shí)現(xiàn)數(shù)據(jù)庫結(jié)構(gòu)的最后一步往往是為其添加索引以優(yōu)化性能。通常,需要為每一個(gè)主鍵和侯選鍵定義唯一性索引。(決大多數(shù)RDBMS在定義主鍵、侯選鍵約束同時(shí)創(chuàng)建唯一性索引)同時(shí),還需

36、要為主鍵和侯選鍵約束未包容的外鍵定義索引。 在此,對索引的重要性特以強(qiáng)調(diào)。主鍵和外鍵上的索引能加速對象模型中的訪問。(實(shí)際上,索引用于兩個(gè)目的:加速數(shù)據(jù)庫的訪問;為主鍵和侯選鍵強(qiáng)制唯一性)數(shù)據(jù)庫實(shí)現(xiàn)必須添加索引,否則,用戶將因不良的性能感到沮喪。在數(shù)據(jù)庫設(shè)計(jì)的早期,就應(yīng)并入索引,因?yàn)樗鼈兊膶?shí)現(xiàn)非常簡易,延遲實(shí)現(xiàn)并不是一個(gè)很好的主意。數(shù)據(jù)庫管理員(DBA)可能會為經(jīng)常使用的查詢定義附加的索引。DBA也可能使用特定于產(chǎn)品的協(xié)調(diào)機(jī)制。4.2 存儲過程(Stored Procedures)存儲過程是運(yùn)行在關(guān)系數(shù)據(jù)庫服務(wù)器端上的函數(shù)/過程。盡管SQL代碼通常是存儲過程的主要組成部分,但大多數(shù)廠商使用特有

37、的語言。典型的存儲過程運(yùn)行一些SQL代碼,進(jìn)行數(shù)據(jù)處理,接著以零行或多行的形式返回,或者顯示錯(cuò)誤信息。存儲過程是現(xiàn)代關(guān)系數(shù)據(jù)庫非常強(qiáng)大的工具。在向關(guān)系數(shù)據(jù)庫映射對象時(shí),假設(shè)未使用Persistent Layer的前提下,有兩種情況使用存儲過程較合理。第一種情況是建立快速的、簡陋的、隨后將遺棄的原型。存儲過程則看上去是建立原型最快速的方法。第二種情況是必須使用已有的數(shù)據(jù)庫。并且,該數(shù)據(jù)庫的設(shè)計(jì)不適用于對象方法,無法使其為特定的要求服務(wù)。則可以適用存儲過程以類似于對象的方法來讀寫記錄。注意,存儲過程并不是唯一的方法;相應(yīng)的,可以使用其它語言來書寫,并在數(shù)據(jù)庫外運(yùn)行代碼。(可能仍在Server端,以

38、避免不必要的網(wǎng)絡(luò)流量)另一方面,有許多充分的理由不使用存儲過程。使用存儲過程,Server端很快成為運(yùn)行的瓶頸。當(dāng)某個(gè)簡單的存儲過程被頻繁的調(diào)用時(shí),會極大地降低數(shù)據(jù)庫的性能。存儲過程一般采用特定于廠商的語言編寫。在不同數(shù)據(jù)庫之間進(jìn)行移植時(shí),甚至在相同數(shù)據(jù)庫的不同版本移植時(shí),會出現(xiàn)很多不可預(yù)見的問題。存儲過程極大地增加了與數(shù)據(jù)庫之間的耦合。它降低了數(shù)據(jù)庫管理的靈活性。在修改數(shù)據(jù)庫時(shí),會要求重寫存儲過程,從而增加了維護(hù)的工作量。底線:存儲過程僅僅是一種用于解決短期問題的蹩腳方法。- 15 -4.3 觸發(fā)器(Triggers)觸發(fā)器實(shí)際上是一種可以自動調(diào)用的存儲過程。在增、刪、改前調(diào)用觸發(fā)器是非常普

39、遍的方法。觸發(fā)器必須成功的運(yùn)行,否則相應(yīng)的操作失敗。觸發(fā)器通常用來保證數(shù)據(jù)庫的完整性。與存儲過程一樣。觸發(fā)器使用特定于廠商的語言,使它們較難移植。好消息是一些建模工具能基于關(guān)系的信息自動生成觸發(fā)器。只要不修改生成的代碼,則可以在跨廠商/版本移植時(shí),為數(shù)據(jù)模型重新生成觸發(fā)器。建議:不使用Trigger,即使在保證數(shù)據(jù)完整性時(shí)。數(shù)據(jù)完整性往往相關(guān)于特定應(yīng)用域,可以在Business Layer或MCV模型中的View層次實(shí)現(xiàn)。- 16 -5. 對象關(guān)系數(shù)據(jù)庫映射的討論 對象設(shè)計(jì)和關(guān)系數(shù)據(jù)庫是常用實(shí)現(xiàn)標(biāo)準(zhǔn) ODBC和JDBC的類是不夠的 需要Persistence層設(shè)計(jì) 硬編碼的SQL語句是很糟糕的

40、主意 必須映射到現(xiàn)存的數(shù)據(jù)庫 數(shù)據(jù)模型不應(yīng)驅(qū)動類設(shè)計(jì) 表連接速度很慢 避免使用帶商業(yè)意義的主鍵 合成主鍵也不宜具有使用 需要多種實(shí)現(xiàn)繼承的策略 存儲過程是一種很蹩腳的方法5.1 對象設(shè)計(jì)和關(guān)系數(shù)據(jù)庫是常用實(shí)現(xiàn)標(biāo)準(zhǔn)由于對象/關(guān)系機(jī)制的不匹配,許多面向?qū)ο蟮脑O(shè)計(jì)者聲稱不應(yīng)使用關(guān)系數(shù)據(jù)庫。但事實(shí)是99%的開發(fā)環(huán)境是面向?qū)ο蟮拈_發(fā)方法和關(guān)系數(shù)據(jù)庫的Persistence機(jī)制,是常用的實(shí)現(xiàn)標(biāo)準(zhǔn)。5.2 ODBC和JDBC的類是不夠的盡管許多開發(fā)環(huán)境提供了初級的訪問關(guān)系數(shù)據(jù)庫的機(jī)制,它們是很好的一個(gè)開始。常用的方法包括Microsoft的ODBC機(jī)制(開放數(shù)據(jù)庫連接ODBC)和Java數(shù)據(jù)庫連接(JDBC

41、),絕大多數(shù)面向?qū)ο蟮拈_發(fā)環(huán)境提供了封裝這些標(biāo)準(zhǔn)方法之一的類庫。這些類庫的基本問題,同它們封裝了許多對本地?cái)?shù)據(jù)庫的訪問一樣,太過于復(fù)雜。在較好設(shè)計(jì)的類庫中,僅僅提供delete、save和retrieve消息來實(shí)現(xiàn)基本的Persistence功能。數(shù)據(jù)庫中與多種對象協(xié)同的界面并不十分復(fù)雜。開發(fā)環(huán)境所提供的訪問數(shù)據(jù)庫的類僅僅是開始,設(shè)計(jì)實(shí)現(xiàn)工作中很小的一部分。5.3 因而,需要Persistence層設(shè)計(jì)Persistence層封裝了對數(shù)據(jù)庫的訪問,允許開發(fā)者專注于商業(yè)領(lǐng)域的問題。即意味著,封裝訪問數(shù)據(jù)庫的類以為開發(fā)者提供足夠簡單的完備接口。另外,對數(shù)據(jù)庫設(shè)計(jì)也提供了封裝,使開發(fā)者無需了解數(shù)據(jù)庫

42、的私有實(shí)現(xiàn)。Persistence層徹底地隱藏了存儲機(jī)制,隔離了可能的修改。以上的討論暗示Persistence層需要數(shù)據(jù)字典提供映射對象所需要的信息。當(dāng)商業(yè)規(guī)則如同以往發(fā)生變化時(shí),Persistence層的代碼應(yīng)無需改變。另外,如果數(shù)據(jù)庫更改時(shí),可能是安裝新的數(shù)據(jù)庫或是DBA重組數(shù)據(jù)表,唯一所需要修改的是數(shù)據(jù)字典中的信息。簡單的數(shù)據(jù)庫的改動不會導(dǎo)致應(yīng)用代碼的變化,如果需要得到易于維護(hù)的永久化方法,數(shù)據(jù)字典非常關(guān)鍵。- 17 -5.4 硬編碼的SQL語句是很糟糕的主意一個(gè)相關(guān)的問題是應(yīng)用程序中的SQL代碼(Structured Query Language)。使用SQL代碼使程序與數(shù)據(jù)庫設(shè)計(jì)耦合在一起,減少了程序的可維護(hù)性和升級能力。其問題在于無論什么時(shí)候數(shù)據(jù)庫發(fā)生改變,可能僅僅是表、列改名或發(fā)生移動,均必須修改程序代碼。另一個(gè)Persistence層可以使用的更好的辦法是:基于數(shù)據(jù)字典的信息生成動態(tài)SQL語句。誠然,動態(tài)SQL運(yùn)行慢一些,但提高了可維

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論