本文僅論述這些選擇中的一種,即在完全關(guān)系數(shù)據(jù)庫(kù)上層面向?qū)ο蟮念惸P瓦M(jìn)行分層。這并不表明它是唯一、最好而又簡(jiǎn)單的解決方案,但是從實(shí)用的角度看,它是最常用的一種類型,卻也是最容易被用錯(cuò)的一種。
我們先快速瀏覽兩個(gè)設(shè)計(jì)領(lǐng)域的模型,并試圖把它們連接起來(lái):第一,介紹用UML表達(dá)面向?qū)ο蟮念惸P?;第二,關(guān)系數(shù)據(jù)庫(kù)模型。
對(duì)每一個(gè)領(lǐng)域我們只涉及影響到我們?nèi)蝿?wù)的主要功能。然后我們將關(guān)注從類模型到數(shù)據(jù)庫(kù)模型映射的技術(shù)和問(wèn)題,包括對(duì)象持久性,對(duì)象行為,對(duì)象和對(duì)象標(biāo)識(shí)之間 的關(guān)系。我們將總結(jié)對(duì)UML數(shù)據(jù)profile的回顧(Rational Software 推薦)。一些面向?qū)ο笤O(shè)計(jì),UML和關(guān)系數(shù)據(jù)庫(kù)建模的相似性也會(huì)被提及。
類模型是UML用來(lái)表達(dá)軟件系統(tǒng)邏輯結(jié)構(gòu)的主要工件。 它用來(lái)記錄數(shù)據(jù)需求和模型領(lǐng)域內(nèi)對(duì)象的行為。本文不討論創(chuàng)建和詳細(xì)描述該模型的技術(shù),我們將假設(shè)已經(jīng)存在一個(gè)設(shè)計(jì)好的類模型,它需要映射到關(guān)系數(shù)據(jù)庫(kù)上。
類模型
類在UML中是一個(gè)基本的邏輯實(shí)體。它定義了一個(gè)結(jié)構(gòu)單元的數(shù)據(jù)和行為。一個(gè)類是一個(gè)模板或運(yùn)行時(shí)創(chuàng)建實(shí)例和對(duì)象的模型。當(dāng)開發(fā)一個(gè)邏輯模型,如UML中 的結(jié)構(gòu)層次,我們將明確地把它們當(dāng)作類來(lái)處理。當(dāng)面對(duì)動(dòng)態(tài)圖時(shí),如順序圖和協(xié)作圖,我們也要處理類的實(shí)例和對(duì)象,以及它們運(yùn)行時(shí)的內(nèi)部動(dòng)作。數(shù)據(jù)隱藏和封 裝原則是基于作用域效果。類有它的內(nèi)部數(shù)據(jù)元素。訪問(wèn)這些數(shù)據(jù)元素需要通過(guò)類對(duì)外的行為或接口。遵循這個(gè)原則會(huì)生成更易于維護(hù)的代碼。
行為
行為使用了類定義的操作,在類模型中被記錄。操作是可以外部可見的(public),對(duì)子類可見的(protected)和隱藏的(private)。通 過(guò)結(jié)合隱藏?cái)?shù)據(jù)和公共訪問(wèn)接口,隱藏或保護(hù)數(shù)據(jù)的操作,類的設(shè)計(jì)人員可以建立極易維護(hù)的結(jié)構(gòu)單元,這些結(jié)構(gòu)單元是支持而不是阻礙變化的。
關(guān)系和特性
關(guān)聯(lián)是兩個(gè)類之間的一種關(guān)系。關(guān)系一側(cè)的類知道和在某種程度上使用或操控另一側(cè)的類。這種關(guān)聯(lián)可以是功能上的(為我做某事)也可以是結(jié)構(gòu)上的(是什么)。 在本文中更多的是側(cè)重結(jié)構(gòu)上的關(guān)系。如:一個(gè)“Address”類可以關(guān)聯(lián)一個(gè)“Person”類,將這種關(guān)系映射到數(shù)據(jù)空間需要多加注意。
聚合是關(guān)聯(lián)的一種形式,表示一個(gè)類多個(gè)對(duì)象的集合在另一個(gè)類中。復(fù)合是一種更強(qiáng)的聚合形式,說(shuō)明一個(gè)對(duì)象實(shí)際上由其它對(duì)象構(gòu)成。對(duì)于關(guān)聯(lián)關(guān)系來(lái)說(shuō),它意味 著一個(gè)復(fù)雜的類屬性,將該屬性映射到關(guān)系模型時(shí)需要更詳細(xì)的考慮。當(dāng)一個(gè)類表示為生成許多對(duì)象實(shí)例的模板或模型時(shí),對(duì)象需要在運(yùn)行時(shí)有識(shí)別自己的方式,這 樣被關(guān)聯(lián)對(duì)象可以對(duì)正確的對(duì)象實(shí)例施加作用。在編程語(yǔ)言中,如C++,對(duì)象指針可能會(huì)傳遞,并使所指對(duì)象可以訪問(wèn)一個(gè)獨(dú)一無(wú)二的對(duì)象實(shí)例。通常盡管一個(gè)對(duì) 象會(huì)被銷毀,但是在需要時(shí),又象上一次有效實(shí)例期間那樣被重建。所以,這些對(duì)象需要一個(gè)存儲(chǔ)機(jī)制來(lái)保留它們的內(nèi)部狀態(tài)和關(guān)聯(lián),并在需要時(shí)恢復(fù)所需狀態(tài)。
繼承給類模型提供一種方式,該方式提取通用行為到泛化的類中,使這個(gè)泛化類稍后可以做為在一般主題上諸多變異的原形。繼承是一種管理重用和復(fù)雜性程度的方 式。如我們將看到的,關(guān)系模型并沒(méi)有與繼承關(guān)系的直接對(duì)應(yīng)項(xiàng),這給數(shù)據(jù)模型建立者建立一個(gè)從對(duì)象模型到關(guān)系框架造成了困難。從一個(gè)運(yùn)行時(shí)的對(duì)象到另外一個(gè) 對(duì)象的導(dǎo)航是建立在完全引用的基礎(chǔ)之上。一個(gè)對(duì)象有多種形式的連接(指針或唯一的對(duì)象標(biāo)識(shí)),用這些連接可以定位和重建所需的對(duì)象。
關(guān)系模型
關(guān)系數(shù)據(jù)模型已經(jīng)使用多年,提供的性能和靈活性一直行之有效。它本質(zhì)上是基于集合的(set-based),并且用‘表’做為它的基本單元,表由一個(gè)或多個(gè)‘列’組成,每一個(gè)列包含一個(gè)數(shù)據(jù)元素。
表和列:一個(gè)關(guān)系表是一個(gè)或多個(gè)列的集合,每個(gè)列在表結(jié)構(gòu)中有一個(gè)唯一名稱,并且被定義成一個(gè)特定基本數(shù)據(jù)類型,如:數(shù)字、文本、二元數(shù)據(jù)。表定義是一個(gè) 模板,表的“行”從這個(gè)模板中被創(chuàng)建,行可能做為一個(gè)表實(shí)例的實(shí)例。關(guān)系模型僅僅提供一個(gè)公共數(shù)據(jù)訪問(wèn)的模型。所有數(shù)據(jù)向外對(duì)任何一個(gè)過(guò)程開放,以便于被 更新,查詢和操控。信息隱蔽(information hiding)是未知的。
行為
與表相關(guān)聯(lián)的行為通常是基于所應(yīng)用實(shí)體的業(yè)務(wù)或邏輯規(guī)則。約束以多個(gè)形式應(yīng)用到“列”,如:獨(dú)特性需求、對(duì)應(yīng)其它表和列的關(guān)系完整性約束,允許的值和數(shù)據(jù)類型。
觸發(fā)器提供了關(guān)聯(lián)到一個(gè)實(shí)體的許多附加行為。通常在數(shù)據(jù)被插入、刪除和更新前后,強(qiáng)制執(zhí)行數(shù)據(jù)的完整性檢查。數(shù)據(jù)庫(kù)存儲(chǔ)過(guò)程提供了一種通過(guò)專有語(yǔ)言擴(kuò)展來(lái) 延伸數(shù)據(jù)庫(kù)功能的方式,這些擴(kuò)展通常用來(lái)構(gòu)造功能性單元(腳本)。這些功能不會(huì)直接映射到這些實(shí)體,也不會(huì)與它們有邏輯關(guān)系。通過(guò)關(guān)系數(shù)據(jù)集的導(dǎo)航是基于 “行”遍歷和表連接實(shí)現(xiàn)。SQL是用來(lái)從表集選擇“行”和放置實(shí)例的一種主要的語(yǔ)言。
關(guān)系和識(shí)別
表的主鍵為識(shí)別行提供一個(gè)特定值。這里有兩種我們關(guān)注的主鍵:首先是意義鍵(meaning key),它由數(shù)據(jù)列構(gòu)成,這些數(shù)據(jù)列在業(yè)務(wù)領(lǐng)域有意義。其次是一個(gè)抽象的唯一標(biāo)識(shí)符,如計(jì)數(shù)器值,它沒(méi)有商業(yè)意義,但是可以唯一地標(biāo)識(shí)一個(gè)行。我們將先 討論抽象唯一標(biāo)識(shí)符,然后再闡述意義鍵。一個(gè)表可以包含映射到另一個(gè)表主鍵的“列”。表間的關(guān)系定義了一個(gè)外鍵,說(shuō)明了在這兩個(gè)表之間的結(jié)構(gòu)關(guān)系或關(guān)聯(lián)。
小節(jié)
從以上的概述,我們可以看出對(duì)象模型是建立在離散實(shí)體基礎(chǔ)上,這些實(shí)體既有狀態(tài)(屬性和數(shù)據(jù)),也有行為,一般僅通過(guò)類的公共接口來(lái)訪問(wèn)封裝數(shù)據(jù)。關(guān)系模 型同等地顯露所有數(shù)據(jù),有限支持利用觸發(fā)器從行為到數(shù)據(jù)元素的關(guān)聯(lián)。依靠使用唯一對(duì)象標(biāo)識(shí)符,可以從一個(gè)對(duì)象移動(dòng)到另一個(gè)對(duì)象,這使得我們可以在對(duì)象模型 中導(dǎo)航,并建立對(duì)象關(guān)系(類似于網(wǎng)絡(luò)數(shù)據(jù)模型)。在關(guān)系模型中,通過(guò)使用檢索標(biāo)準(zhǔn),SQL合并和過(guò)濾結(jié)果集,你可以查找找所需的行。標(biāo)識(shí)符在對(duì)象模型中既 可以是實(shí)時(shí)引用,也可以是持久的唯一標(biāo)識(shí)符(稱作OID)。在關(guān)系領(lǐng)域里,主鍵定義了數(shù)據(jù)集在整個(gè)數(shù)據(jù)空間中的唯一性。
對(duì)象模型中有豐富的關(guān)系集合:繼承,聚合,關(guān)聯(lián),復(fù)合,依賴,以及其它。在關(guān)系模型中,可以僅使用外鍵來(lái)指明一種關(guān)系。我們已經(jīng)對(duì)感興趣的兩個(gè)領(lǐng)域進(jìn)行了介紹并比較了每一個(gè)領(lǐng)域的幾個(gè)重要功能,然后將簡(jiǎn)單了解UML中關(guān)系數(shù)據(jù)模型的標(biāo)注。
UML數(shù)據(jù)模型Profile(特性描述)
數(shù)據(jù)模型Profile是Enterprise Architect的UML擴(kuò)展來(lái)支持關(guān)系數(shù)據(jù)庫(kù)建模。它包括一些定制擴(kuò)展,如:表,數(shù)據(jù)庫(kù)圖表,表鍵,觸發(fā)器和約束。它是一種在UML中對(duì)關(guān)系數(shù)據(jù)庫(kù)建模的技術(shù)。
表和列 表在UML數(shù)據(jù)Profile中是帶《Table》構(gòu)造型的類,它在右上角顯示一個(gè)表的符號(hào)。數(shù)據(jù)庫(kù)中的列用《Table》類的屬性來(lái)建模。
例如:上面圖型顯示與客戶表關(guān)聯(lián)的屬性。在此示例中,對(duì)象ID被定義為表的主鍵,還有兩個(gè)列:“Name”和“Address”。注意上圖例子中列的數(shù)據(jù)類型是按照原DBMS的數(shù)據(jù)類型定義的。
行為 到目前為止,我們僅定義了表的邏輯(靜態(tài))結(jié)構(gòu)。此外,我們將描述與列關(guān)聯(lián)的行為,包括:索引,鍵,觸發(fā)器,過(guò)程等等。行為表示為帶構(gòu)造型的操作。
下圖顯示我們討論的表,它有一個(gè)主鍵約束和索引,均被定義為帶構(gòu)造型的操作。
注意:“OID”列上的PK標(biāo)簽定義了邏輯主鍵,而構(gòu)造型操作“?PK? idx_customer00”定義了與主鍵實(shí)現(xiàn)相關(guān)聯(lián)的約束和行為(即主鍵的行為)。
對(duì)上例進(jìn)行增加,我們現(xiàn)在可以定義附加行為,如:觸發(fā)器,約束,存儲(chǔ)過(guò)程。見下圖:
這個(gè)例子描述了下列行為:
使用上面提供的標(biāo)注,我們可以在DBMS層次上,對(duì)復(fù)雜的數(shù)據(jù)結(jié)構(gòu)和行為建模。另外,UML還提供表達(dá)邏輯實(shí)體間關(guān)系的標(biāo)注。
關(guān)系
UML數(shù)據(jù)建模profile定義了兩個(gè)表間任意一種依賴關(guān)系。它表示為一構(gòu)造型的關(guān)聯(lián)并包括一組主鍵和外鍵。數(shù)據(jù)profile仍然需要一種關(guān)系一直參 與到父類和子類之間,父類定義一個(gè)主鍵,子類實(shí)現(xiàn)一個(gè)建立于全部或部分父類主鍵基礎(chǔ)上的外鍵。這種關(guān)系將被區(qū)分為:“定義的”(如果該子類外鍵包含所有父 類主鍵元素)和“非定義的”(如果只包括部分主鍵元素)。這個(gè)關(guān)系可以包括基數(shù)性約束,以及采用成對(duì)的相關(guān)主鍵與外鍵來(lái)建模,并命名為關(guān)聯(lián)角色。下圖描述 了使用UML對(duì)這種關(guān)系的建模。
物理模型
UML也提供一些機(jī)制來(lái)表示數(shù)據(jù)庫(kù)的整體物理結(jié)構(gòu),它的內(nèi)容和部署位置。我們用構(gòu)造型組件來(lái)表示一個(gè)物理數(shù)據(jù)庫(kù)。見下圖:
一個(gè)組件表示了一個(gè)離散,可部署的實(shí)體。在物理模型中,組件可以映射到一個(gè)物理硬件(UML的節(jié)點(diǎn))。對(duì)于數(shù)據(jù)庫(kù)內(nèi)的關(guān)系模式,我們用帶《Schema》 構(gòu)造型的包來(lái)表示。一個(gè)表可以放置到《Schema》中來(lái)建立它在數(shù)據(jù)庫(kù)中的范圍和位置。
從類模型到關(guān)系模型的映射
我們已經(jīng)描述了所關(guān)注的兩個(gè)領(lǐng)域和它們使用的標(biāo)注,現(xiàn)在將我們的注意力轉(zhuǎn)移到如何映射,及如何從一個(gè)領(lǐng)域轉(zhuǎn)換到另一個(gè)領(lǐng)域。以下采用的策略和表達(dá)順序是建議性的,而不是必須的。采用何種步驟和過(guò)程要根據(jù)個(gè)人的需要和環(huán)境而定。
1. 類的建模
首先我們假設(shè)從一個(gè)已經(jīng)創(chuàng)建的類模型構(gòu)建一個(gè)新的關(guān)系數(shù)據(jù)庫(kù)模式。顯然這是一個(gè)最容易的方向,這是因?yàn)槟P鸵恢痹谖覀兊目刂浦?,并且我們能根?jù)類模型來(lái) 優(yōu)化這關(guān)系模型。在現(xiàn)實(shí)環(huán)境下,你可能需要在原有數(shù)據(jù)模型之上對(duì)類模型分層,這是更難的一種情況,具有挑戰(zhàn)性。在這里,我們只關(guān)注第一種情況。至少類模型 會(huì)記錄元素的關(guān)聯(lián),繼承和聚合關(guān)系。
2. 標(biāo)識(shí)持久對(duì)象
建立類模型后,我們需要將類模型的元素分成需要持久性和不需要持久性兩類。例如,如果我們采用“模型-視圖-控制”的設(shè)計(jì)模式來(lái)設(shè)計(jì)我們的應(yīng)用程序,那么只在模型部分的類將需要持久狀態(tài)。
3. 假設(shè)每一個(gè)持久類映射到一個(gè)關(guān)系表
這是一個(gè)大的假設(shè),但是它對(duì)大多數(shù)情況有用(現(xiàn)在先把繼承的問(wèn)題放一邊)。在一個(gè)最簡(jiǎn)單模型中,一個(gè)來(lái)自邏輯模型的類映射到關(guān)系表的全部或一部分。這個(gè)映射的邏輯擴(kuò)展是一個(gè)單獨(dú)的對(duì)象(或類的實(shí)例)映射到表中單獨(dú)的“行”。
4. 選擇一個(gè)繼承策略.
繼承可能是從面向?qū)ο竽P娃D(zhuǎn)換到關(guān)系模型過(guò)程中最容易出現(xiàn)問(wèn)題的關(guān)系和邏輯結(jié)構(gòu)。關(guān)系領(lǐng)域本質(zhì)上是平面的,每一個(gè)實(shí)體自身完成,而對(duì)象模型常常是一個(gè)具有 深度的,設(shè)計(jì)完善的類層次結(jié)構(gòu)。這樣深度的類模型可以有多層的繼承屬性和行為,運(yùn)行時(shí)生成最后全功能的對(duì)象:
對(duì)每一種方法,我們有對(duì)應(yīng)的案例。但是我們推薦第三種方法,因?yàn)樗詈?jiǎn)單,最容易維護(hù)和最不容易出錯(cuò)。第一種方法提供了運(yùn)行時(shí)最佳的性能。第二種方法是第 一種與第三種的折衷。第一種方法展開層次結(jié)構(gòu),在一個(gè)表里放置所有的屬性,這樣方便類層次結(jié)構(gòu)中對(duì)類的更新和提取,但是不易于驗(yàn)證和維護(hù)。與“行”關(guān)聯(lián)的 業(yè)務(wù)規(guī)則是難以實(shí)現(xiàn)的,因?yàn)楸碇械拿恳恍卸伎赡鼙粚?shí)例化為層次結(jié)構(gòu)中的對(duì)象?!傲小敝g的依賴關(guān)系可能變得相當(dāng)復(fù)雜。此外,對(duì)層次結(jié)構(gòu)中任何一個(gè)類的更新 將可能影響層次結(jié)構(gòu)中其它每個(gè)類,如表中的列被添加,刪除和修改。
第二種方法是一種折衷方案,提供了更好的封裝和消除空列。可是,對(duì)父類的修改可能需要在所有子類的表中進(jìn)行復(fù)制,更糟的是,有兩個(gè)或多個(gè)子類的父類數(shù)據(jù)可 能被冗余地存儲(chǔ)在許多表中;如果父類的屬性被修改,那么要花相當(dāng)?shù)臅r(shí)間去查找相關(guān)的子表,并更新受影響的行。
第三種方法精確地反映了對(duì)象模型,它將層次結(jié)構(gòu)中的每一個(gè)類映射成一個(gè)獨(dú)立的表。父類或子類的更新是在正確空間的局部范圍內(nèi)進(jìn)行的。對(duì)實(shí)體的任何修改被嚴(yán) 格限定于單個(gè)表內(nèi),因此表的維護(hù)也就相對(duì)簡(jiǎn)單。缺點(diǎn)是需要在運(yùn)行時(shí)重構(gòu)結(jié)構(gòu)層次,來(lái)精確產(chǎn)生一個(gè)子類的狀態(tài)。一個(gè)“Child”的對(duì)象可能需要一個(gè) “Person”的成員變量用于表示它的父輩。由于這兩者都需要加載,兩次調(diào)用數(shù)據(jù)庫(kù)來(lái)初始化一個(gè)對(duì)象。隨著類結(jié)構(gòu)層次加深,初始化或更新一個(gè)單獨(dú)對(duì)象的 數(shù)據(jù)庫(kù)調(diào)用次數(shù)也隨之增加。
當(dāng)你映射繼承關(guān)系到關(guān)系模型時(shí),理解上述要點(diǎn)是很重要的,這樣你就選擇最適合你的方案。
5. 為每一個(gè)類添加一個(gè)唯一的對(duì)象標(biāo)識(shí)符
在關(guān)系和對(duì)象的領(lǐng)域里,需要唯一標(biāo)識(shí)一個(gè)對(duì)象或?qū)嶓w。在對(duì)象模型中,非持久對(duì)象在運(yùn)行時(shí)通常被直接引用或?qū)ο笾羔榿?lái)標(biāo)識(shí)。一旦對(duì)象被創(chuàng)建,我們可以用它運(yùn) 行時(shí)的標(biāo)識(shí)符來(lái)引用它。但是,如果我們將對(duì)象寫入存儲(chǔ)空間,那么如何按需要得到完全相同的實(shí)例是一個(gè)問(wèn)題。最便捷的方式是定義一個(gè)OID(對(duì)象標(biāo)識(shí)符), 它在關(guān)注的命名空間是被確保唯一的。根據(jù)需要,這可能發(fā)生在類,包或系統(tǒng)的層級(jí)上。
系統(tǒng)級(jí)別OID的一個(gè)例子可以是一個(gè)使用微軟“guidgen”工具創(chuàng)建的GUID(全局唯一標(biāo)識(shí)符),如{A1A68E8E-CD92-420b- BDA7-118F847B71EB}。類級(jí)別的OID可以用簡(jiǎn)單得數(shù)字實(shí)現(xiàn)(如:32位計(jì)數(shù)器)。如果一個(gè)對(duì)象具有對(duì)其它對(duì)象的引用,它可以采用使用它 們的OID的方法。那么,在運(yùn)行時(shí)有效地將引用的對(duì)象從存儲(chǔ)區(qū)加載到模型中。關(guān)于上述OID值的重點(diǎn)是它沒(méi)有超出定義它為標(biāo)識(shí)符的簡(jiǎn)單含義。它們僅是邏輯 指針而沒(méi)有其它意義。在關(guān)系模型中,情況往往是不同的。
關(guān)系模型中標(biāo)識(shí)正常地用一個(gè)主鍵實(shí)現(xiàn)。主鍵是一個(gè)表中的一組“列”,它們合起來(lái)可以唯一地標(biāo)識(shí)一個(gè)行。例如:名稱和地址可以唯一地標(biāo)識(shí)一個(gè)“客戶”。其它 實(shí)體,如:“銷售員”引用“客戶”,它們要實(shí)現(xiàn)基于“客戶”主鍵的外鍵。這個(gè)方法存在的問(wèn)題是:將業(yè)務(wù)信息(如客戶名和地址)嵌入標(biāo)識(shí)符中對(duì)我們目標(biāo)的影 響。設(shè)想三個(gè)或四個(gè)表全部具有基于“客戶”主鍵的外鍵,對(duì)于一個(gè)需要修改客戶主鍵(如:增加一個(gè)用戶類型)的系統(tǒng)修改,那么既要修改客戶表,也要修改與外 鍵相關(guān)的實(shí)體,這個(gè)工作是十分巨大的。
另一方面,如果一個(gè)OID被當(dāng)作主鍵實(shí)現(xiàn),并為其它表建立外鍵,那么修改范圍僅限于主表,并且修改的影響也因此大大減小。實(shí)際上,一個(gè)基于業(yè)務(wù)數(shù)據(jù)的主鍵 也許會(huì)被修改。如:一個(gè)客戶可以修改地址和名字,既然這樣,這個(gè)變化需要被正確的傳遞到所有其它相關(guān)的實(shí)體,更不用提改變部分主鍵信息的困難。
一個(gè)OID總是引用同一個(gè)實(shí)體,而不管其它信息怎么改變。在上面的例子中,客戶可以修改名稱和地址,與它相關(guān)聯(lián)的表不需要被修改。當(dāng)把對(duì)象模型映射到關(guān)系 表時(shí),實(shí)現(xiàn)完全OID的標(biāo)識(shí)符比采用業(yè)務(wù)聯(lián)系的主鍵更加便捷。用OID做為主鍵和外鍵的方法將為對(duì)象提供更好的加載和更新效率,將維護(hù)服務(wù)減到最少。實(shí)際 上,一個(gè)與業(yè)務(wù)相聯(lián)系的主鍵可以替換為:
再次重申,是使用有意義的鍵還是使用OID取決于被開發(fā)系統(tǒng)的實(shí)際需要。
6. 映射屬性到“列”
通常,我們將簡(jiǎn)單的類數(shù)據(jù)屬性映射到關(guān)系表的列。例如,一個(gè)文本或數(shù)字字段可以分別表示一個(gè)人的名字和年齡,這種直接映射不會(huì)引起什么問(wèn)題,只是簡(jiǎn)單地在數(shù)據(jù)庫(kù)服務(wù)商的關(guān)系模型中選擇適當(dāng)?shù)模c類屬性相對(duì)應(yīng)的數(shù)據(jù)類型。
對(duì)復(fù)雜屬性(即屬性為其它對(duì)象)使用下面詳細(xì)的步驟來(lái)處理關(guān)聯(lián)和聚合關(guān)系。
7. 映射關(guān)聯(lián)到外鍵
更復(fù)雜的類屬性(即它們代表其它類)通常建模為關(guān)聯(lián)關(guān)系。一個(gè)關(guān)聯(lián)是對(duì)象間的結(jié)構(gòu)關(guān)系。例如,一個(gè)人可以居住在一個(gè)地址,當(dāng)這個(gè)人被建模,他會(huì)有城市,街 道,郵編的屬性。在對(duì)象和關(guān)系領(lǐng)域里,我們傾向于把這個(gè)信息當(dāng)作單獨(dú)的實(shí)體來(lái)構(gòu)造:“地址”。在對(duì)象領(lǐng)域里,地址代表一個(gè)獨(dú)一無(wú)二的物理對(duì)象,并可能帶有 一個(gè)唯一OID。在關(guān)系領(lǐng)域,一個(gè)地址可以是地址表中的一行,該表的主鍵被用作為其它實(shí)體的外鍵。
在這兩種模型中,趨向于移動(dòng)地址信息到獨(dú)立實(shí)體,這有助于避免冗余數(shù)據(jù)和提高可維護(hù)性。所以對(duì)于每一個(gè)類模型中的關(guān)聯(lián),要考慮創(chuàng)建一個(gè)從子類到父類表的外鍵。
8. 映射聚合和復(fù)合
聚合和復(fù)合關(guān)系類似于關(guān)聯(lián)關(guān)系,并通過(guò)“主鍵-外鍵”對(duì)來(lái)映射成表。但是,需要提醒的是:普通聚合(弱聚合)對(duì)關(guān)系建模,如:一個(gè)人住在一個(gè)或多個(gè)地址, 在此例中,超過(guò)一個(gè)以上的人可能住在相同地址,如果這個(gè)人不在這里住了,與他相連的地址仍然存在。這個(gè)例子例舉了關(guān)系術(shù)語(yǔ)中稱之為“多對(duì)多的關(guān)系”,并且 通常實(shí)現(xiàn)為一個(gè)獨(dú)立的表,該表包含了從一個(gè)表格的主鍵到另一個(gè)表格主鍵的映射。
弱聚合的第二個(gè)例子是:一個(gè)實(shí)體在那里使用或排除了另一個(gè)實(shí)體的所有權(quán)。例如:一個(gè)“人”的實(shí)體擁有一組股票,這標(biāo)明這個(gè)人可能與一個(gè)“股票”表中的某些 股票有關(guān)聯(lián),也可能沒(méi)有關(guān)系。但是每個(gè)股票可以聯(lián)系一個(gè)人,或不與任何人發(fā)生關(guān)系。如果這個(gè)人不在了,這個(gè)股票將變?yōu)椤盁o(wú)主”的,或者被傳遞給下一個(gè)人。 在這個(gè)關(guān)系模型中,可以通過(guò)每個(gè)股票有一個(gè)“所有者”列來(lái)實(shí)現(xiàn),這個(gè)“所有者”列將存儲(chǔ)一個(gè)人的標(biāo)識(shí)符(OID)。
強(qiáng)聚合形式則有與之關(guān)聯(lián)的完整約束。復(fù)合表明一個(gè)實(shí)體由部件組成,并且這些部件對(duì)整體有依賴關(guān)系。例如:一個(gè)人可以有很多證明文件,如護(hù)照,出生證明,駕 照等。這個(gè)人的實(shí)體可以由這樣的一組文件組成。如果這個(gè)人從系統(tǒng)里被刪除,那么證明文件也要被刪除,因?yàn)檫@些文件被映射到一個(gè)唯一個(gè)體。
如果我們暫時(shí)忽略O(shè)ID,弱聚合可能使用中間表來(lái)實(shí)現(xiàn)(對(duì)多對(duì)多的情況)或者在一個(gè)聚合的類或表采用一個(gè)外鍵來(lái)實(shí)現(xiàn)(一對(duì)多的情況)。在多對(duì)多關(guān)系的情況 下,如果父類被刪除,中間表中的實(shí)體也要被刪除。在一對(duì)多的情況下,如果父類被刪除,外鍵輸入(如“所有者”)必須被清除。
在復(fù)合的情況下,外鍵的使用是強(qiáng)制的,約束條件是父類刪除后,部件也必須被刪除。邏輯上,復(fù)合是有一種含義,部件主鍵形成了全部主鍵的一部分。例如:一個(gè)人的主鍵由他證明文件組成。盡管實(shí)際上是相當(dāng)冗長(zhǎng)的,但邏輯關(guān)系上為真。
9. 定義關(guān)系作用
對(duì)于每一個(gè)關(guān)聯(lián)關(guān)系,可能會(huì)進(jìn)一步指明關(guān)系每一個(gè)端點(diǎn)的角色信息。通常包含主鍵約束名和外鍵約束名。圖6例示了這個(gè)概念,這在邏輯上定義兩個(gè)類之間的關(guān) 系。另外,可能會(huì)在作用名上標(biāo)明附加約束(即{非空})和基數(shù)性約束(即0..n)。
10. 模型行為
我們現(xiàn)在來(lái)討論另一個(gè)難題:是映射部分還是所有的類行為到數(shù)據(jù)庫(kù)商提供的功能上,這些功能以觸發(fā)器,存儲(chǔ)過(guò)程,唯一性,數(shù)據(jù)約束和關(guān)系完整性的形式出現(xiàn)。 一個(gè)非持久對(duì)象模型通??梢詫?shí)現(xiàn)一種或多種語(yǔ)言(如Java和C++)需要的所有行為。每一個(gè)類將用公共的,保護(hù)的和私有的方式描述它被賦予的行為和職 責(zé)。
不同數(shù)據(jù)庫(kù)商的關(guān)系數(shù)據(jù)庫(kù)通常包含不同形式的,基于SQL的可編程腳本語(yǔ)言,用來(lái)實(shí)現(xiàn)對(duì)數(shù)據(jù)的操作。最常用的例子 是觸發(fā)器和存儲(chǔ)過(guò)程。當(dāng)我們混合對(duì)象和關(guān)系模型,要做的決定往往是:是實(shí)現(xiàn)類模型中所有的業(yè)務(wù)邏輯,還是將部分的業(yè)務(wù)邏輯放在關(guān)系DBMS中更常用而有效 率的觸發(fā)器和存儲(chǔ)過(guò)程中。從完全面向?qū)ο蟮慕嵌瓤?,答案是避免使用觸發(fā)器和存儲(chǔ)過(guò)程,并且將所有行為放到類中。這樣會(huì)使行為局部化,從而提供了一個(gè)更清晰 的設(shè)計(jì),簡(jiǎn)化了維護(hù),并且提供了在不同DBMS提供商之間更好的移植性。
在現(xiàn)實(shí)世界,存儲(chǔ)過(guò)程和觸發(fā)器的設(shè)計(jì)目標(biāo)底線可以是每秒至少執(zhí)行幾百次或幾千次之多。如果為了追求模型的清晰,移植性,可維護(hù)性和靈活性,那么就將所有的行為放在對(duì)象方法中。
如果性能是關(guān)注的焦點(diǎn),可以考慮將部分行為交給更有效的DBMS編程語(yǔ)言。注意到將對(duì)象模型與存儲(chǔ)過(guò)程以安全方式集成所花的額外時(shí)間,包括遠(yuǎn)程影響和調(diào)試的問(wèn)題,可能要比簡(jiǎn)單部署更高性能的硬件更多。
如前面所述,UML數(shù)據(jù)profile提供下列擴(kuò)展(構(gòu)造型操作),可用來(lái)對(duì)DBMS行為建模:
11. 產(chǎn)生物理模型
在UML中,物理模型描述了物體如何在現(xiàn)實(shí)世界里部署:硬件平臺(tái),網(wǎng)絡(luò)連接,軟件,操作系統(tǒng),動(dòng)態(tài)連接庫(kù)和其它組件。你需要生成一個(gè)物理模型來(lái)完成這個(gè)周 期:從一個(gè)初始的用例或領(lǐng)域模型,到類模型和數(shù)據(jù)模型,最后到部署模型。通常對(duì)這個(gè)模型,你要?jiǎng)?chuàng)建一個(gè)或多個(gè)節(jié)點(diǎn),這些節(jié)點(diǎn)可以存放數(shù)據(jù)庫(kù),并安裝 DBMS組件。如果數(shù)據(jù)庫(kù)被分成多于一個(gè)的DBMS實(shí)例,你可以分配表的包《Schema》給單個(gè)DBMS組件來(lái)指明數(shù)據(jù)位置。
總結(jié)
使用UML進(jìn)行數(shù)據(jù)庫(kù)建模,就象你看到的,當(dāng)從對(duì)象領(lǐng)域映射到關(guān)系領(lǐng)域時(shí),有很多要注意的問(wèn)題。UML提供了這兩個(gè)領(lǐng)域之間的橋梁。UML數(shù)據(jù)profile也是一種成功地把兩個(gè)領(lǐng)域集成起來(lái)的優(yōu)秀的擴(kuò)展語(yǔ)言。
聯(lián)系客服