日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

對(duì)象-關(guān)系數(shù)據(jù)庫(kù)之間的映射

 todaytomo 2007-03-28
對(duì)象-關(guān)系數(shù)據(jù)庫(kù)之間的映射
Scott W. Ambler
Ronin International 的總裁
2000 年 7 月

 

 

為什么對(duì)象-關(guān)系數(shù)據(jù)庫(kù)的映射對(duì)于現(xiàn)代開(kāi)發(fā)者是一件大事呢?一方面,對(duì)象技術(shù)(例如 Java 技術(shù))是應(yīng)用于新軟件系統(tǒng)開(kāi)發(fā)的最常見(jiàn)的環(huán)境。另外,關(guān)系數(shù)據(jù)庫(kù)仍然是許多人都青睞的持久信息存儲(chǔ)方法,并且在較長(zhǎng)時(shí)間內(nèi)這種情況不太會(huì)改變。請(qǐng)繼續(xù)讀下去,了解如何使用這種技術(shù)。

為什么要寫有關(guān)對(duì)象-關(guān)系數(shù)據(jù)庫(kù)之間的映射的文章呢?因?yàn)樵趯?duì)象范例和關(guān)系范例之間“阻抗不匹配”。對(duì)象范例基于軟件工程的一些原理,例如耦合、聚合和封裝,而關(guān)系范例則基于數(shù)學(xué)原理,特別是集合論的原理。兩種不同的理論基礎(chǔ)導(dǎo)致各自有不同的優(yōu)缺點(diǎn)。而且,對(duì)象范例側(cè)重于從包含數(shù)據(jù)和行為的對(duì)象中構(gòu)建應(yīng)用程序,而關(guān)系范例則主要針對(duì)數(shù)據(jù)的存儲(chǔ)。當(dāng)為訪問(wèn)而尋找一種合適的方法時(shí),“阻抗不匹配”就成了主要矛盾:使用對(duì)象范例,您是通過(guò)它們的關(guān)系來(lái)訪問(wèn)對(duì)象,而使用關(guān)系范例,則通過(guò)復(fù)制數(shù)據(jù)來(lái)聯(lián)接表中的行。這種基本的差異導(dǎo)致兩種范例的結(jié)合并不理想,不過(guò)話說(shuō)回來(lái),本來(lái)就預(yù)料到會(huì)有一些問(wèn)題。使對(duì)象-關(guān)系數(shù)據(jù)庫(kù)之間的映射成功的一個(gè)秘訣就是理解這兩種范例和它們的差異,然后基于這些認(rèn)識(shí)來(lái)進(jìn)行明智的取舍。

本文應(yīng)該能夠消除現(xiàn)今開(kāi)發(fā)周期中一些普遍共有的誤解,對(duì)對(duì)象-關(guān)系數(shù)據(jù)庫(kù)之間映射所涉及到的一些問(wèn)題提供了切合實(shí)際的看法。這些策略基于我的開(kāi)發(fā)經(jīng)驗(yàn),項(xiàng)目范圍從小到大,涉及金融、銷售、軍事、遠(yuǎn)程通信和外購(gòu)等行業(yè)。我已對(duì)使用 C++、 Smalltalk、Visual Basic 和 Java 語(yǔ)言編寫的應(yīng)用程序應(yīng)用了這些原則。

如何將對(duì)象映射成關(guān)系數(shù)據(jù)庫(kù)
在這一節(jié)中,我會(huì)描述一些將對(duì)象成功映射成關(guān)系數(shù)據(jù)庫(kù)所需的基本技術(shù)。

將屬性映射成列
類屬性將映射成關(guān)系數(shù)據(jù)庫(kù)中的零或幾列。要記住,并不是所有屬性都是持久的。例如, Invoice 類會(huì)有 grandTotal 屬性,這個(gè)屬性由其實(shí)例在計(jì)算時(shí)使用,但它不保存到數(shù)據(jù)庫(kù)中。而且,某些對(duì)象屬性本身就是對(duì)象,例如 Course 對(duì)象有一個(gè)作為屬性的 TextBook 實(shí)例,它映射為數(shù)據(jù)庫(kù)中的幾列(實(shí)際上,很有可能 TextBook 類本身就將映射成一個(gè)或多個(gè)表)。重要的是,這是一個(gè)遞歸定義:有時(shí)屬性將映射成零或者多列。也有可能將幾個(gè)屬性映射成表中的單一列。例如,代表美國(guó)郵遞區(qū)號(hào)代碼的類可以有三個(gè)數(shù)字屬性,每個(gè)都表示完整郵政編號(hào)代碼中的每一部分,而郵政編號(hào)代碼可以在地址表中作為單一的列存儲(chǔ)。

在關(guān)系數(shù)據(jù)庫(kù)中實(shí)現(xiàn)繼承
在將對(duì)象保存到關(guān)系數(shù)據(jù)庫(kù)中時(shí),繼承的概念中發(fā)生幾個(gè)有趣的問(wèn)題。(請(qǐng)參閱

圖 1. 簡(jiǎn)單類層次結(jié)構(gòu)的 UML 類示意圖
圖 1. 簡(jiǎn)單類層次結(jié)構(gòu)的 UML 類示意圖

將類映射成表
類到表的映射通常不是直接的。除了非常簡(jiǎn)單的數(shù)據(jù)庫(kù)以外,您不會(huì)有類到表的一對(duì)一映射。在以下章節(jié)中,我將討論為關(guān)系數(shù)據(jù)庫(kù)實(shí)現(xiàn)繼承結(jié)構(gòu)的三種策略:



整個(gè)類層次結(jié)構(gòu)使用一個(gè)數(shù)據(jù)實(shí)體
使用這種方法,您可以將一個(gè)完整類層次結(jié)構(gòu)映射成一個(gè)數(shù)據(jù)實(shí)體,而層次結(jié)構(gòu)中所有類的所有屬性都存儲(chǔ)在這個(gè)實(shí)體中。圖 2 描述了采取這個(gè)方法時(shí)圖 1 的類層次結(jié)構(gòu)的持久模型。請(qǐng)注意,為表的主鍵引入了一個(gè) personOID 列 - 我在所有解決方案中都使用 OID (沒(méi)有商業(yè)含義的標(biāo)識(shí),又稱替代鍵),只是為了保持一致和使用我所知道的向數(shù)據(jù)實(shí)體分配鍵的最好辦法。

圖 2. 將類層次結(jié)構(gòu)映射成單一數(shù)據(jù)實(shí)體
圖 2. 將類層次結(jié)構(gòu)映射為單一數(shù)據(jù)實(shí)體

這種方法的優(yōu)點(diǎn)是簡(jiǎn)單,因?yàn)樗璧乃腥藛T數(shù)據(jù)都可以在一張表中找到,所以在人們更改角色時(shí)支持多態(tài)性,并且使用這種方法,專門報(bào)告(為一小組用戶特定目的所執(zhí)行的報(bào)告,這些用戶通常自己寫報(bào)告)也非常簡(jiǎn)單。缺點(diǎn)是每次在類層次結(jié)構(gòu)的任何地方添加一個(gè)新屬性時(shí)都必須將一個(gè)新屬性添加到表中。這增加了類層次結(jié)構(gòu)中的耦合 - 如果在添加一個(gè)屬性時(shí)有任何錯(cuò)誤,除獲得新屬性的類的子類外,還可能影響到層次結(jié)構(gòu)中的所有類。它還可能浪費(fèi)數(shù)據(jù)庫(kù)中的許多空間。我還必須添加 objectType 列來(lái)表明行代表的是學(xué)生、教授還是其它類型的人員。在人們具有單一角色時(shí)這種方法很有效,但如果他們有多個(gè)角色(例如,一個(gè)人既是學(xué)生又是教授),很快就會(huì)失效。

每個(gè)具體類使用一個(gè)數(shù)據(jù)實(shí)體
使用這種方法,每個(gè)數(shù)據(jù)實(shí)體就既包含屬性又包含它所表示的類繼承的屬性。圖 3 描述了采取這個(gè)方法時(shí)圖 1 的類層次結(jié)構(gòu)的持久模型。有與 Student 類對(duì)應(yīng)的和與 Professor 類對(duì)應(yīng)的數(shù)據(jù)實(shí)體,因?yàn)樗鼈兪蔷唧w類,但沒(méi)有與 Person 類對(duì)應(yīng)的數(shù)據(jù)實(shí)體,因?yàn)樗浅橄箢悾ㄋ拿Q以斜體字表示)。為每個(gè)數(shù)據(jù)實(shí)體都分別分配了自己的主鍵, studentOIDprofessorOID

圖 3. 將每個(gè)具體類映射成單個(gè)數(shù)據(jù)實(shí)體
圖 3. 將每個(gè)具體類映射成單個(gè)數(shù)據(jù)實(shí)體

這種方法最大的好處是,它仍然能相當(dāng)容易地執(zhí)行專門報(bào)告,只要您所需的有關(guān)單一類的所有數(shù)據(jù)都只存儲(chǔ)在一張表中。但也有幾個(gè)缺點(diǎn)。一個(gè)是當(dāng)修改類時(shí),必須修改它的表和它所有子類的表。例如,如果要向 Person 類添加高度和重量,就需要同時(shí)更新兩個(gè)表,它會(huì)涉及很多工作。第二,無(wú)論何時(shí),只要對(duì)象更改了它的角色 - 可能您聘用了您一個(gè)剛畢業(yè)的學(xué)生作為教授 - 則需要將數(shù)據(jù)復(fù)制到相應(yīng)的表中,并為它指定一個(gè)新的 OID。這又涉及到很多工作。第三,很難在支持多個(gè)角色的同時(shí)仍維護(hù)數(shù)據(jù)完整性。(這種情況是可能的;只是比原先困難一點(diǎn)。)例如,您會(huì)在哪里存儲(chǔ)既是學(xué)生又是教授的人的姓名呢?

每個(gè)類使用一個(gè)數(shù)據(jù)實(shí)體
使用這種方法,為每個(gè)類創(chuàng)建一張表,它的屬性是 OID 和特定于該類的屬性。圖 4 描述了采取這個(gè)方法時(shí)圖 1 的類層次結(jié)構(gòu)的持久模型。 請(qǐng)注意,將 personOID 用作了所有三個(gè)數(shù)據(jù)實(shí)體的主鍵。圖 4 的一個(gè)有趣的特性是,為 ProfessorStudent 中的 personOID 列都分配了兩個(gè)構(gòu)造型,而這在標(biāo)準(zhǔn)建模語(yǔ)言 (UML) 中是不允許的。我的意見(jiàn)是,這是一個(gè)必須由 UML 持久性建模概要解決的問(wèn)題,甚至可能在這個(gè)建模規(guī)則中也需要更改。(有關(guān)持久性模型的詳細(xì)信息,請(qǐng)參閱

圖 4. 將每個(gè)類映射成它自己的數(shù)據(jù)實(shí)體
圖 4. 將每個(gè)類映射成它自己的數(shù)據(jù)實(shí)體

這種方法的最大好處就是它能夠最好地適應(yīng)面向?qū)ο蟮母拍?。它能夠很好地支持多態(tài)性,對(duì)于對(duì)象可能有的每個(gè)角色,只需要在相應(yīng)的表中保存記錄。修改超類和添加新的子類也非常容易,因?yàn)槟恍枰薷幕蛱砑右粡埍?。這種方法也有幾個(gè)缺點(diǎn)。第一,數(shù)據(jù)庫(kù)中有大量的表 -- 實(shí)際上每類都有一個(gè)(加上維護(hù)關(guān)系的表)。第二,使用這種技術(shù)讀取和寫入數(shù)據(jù)的時(shí)間比較長(zhǎng),因?yàn)槟仨氃L問(wèn)多個(gè)表。如果通過(guò)將類層次結(jié)構(gòu)中的每個(gè)表放入不同物理磁盤驅(qū)動(dòng)器盤片(假設(shè)每個(gè)磁盤驅(qū)動(dòng)器磁頭都單獨(dú)操作)上來(lái)智能地組織數(shù)據(jù)庫(kù)的話,就可以緩解這個(gè)問(wèn)題。第三,有關(guān)數(shù)據(jù)庫(kù)的專門報(bào)告很困難,除非添加一些視圖來(lái)模擬所需的表。

比較映射策略
現(xiàn)在,請(qǐng)注意,每個(gè)映射策略怎樣產(chǎn)生不同的模型。要理解三種策略之間的設(shè)計(jì)優(yōu)缺點(diǎn),請(qǐng)考慮圖 5 中顯示的對(duì)我們的類層次結(jié)構(gòu)做些簡(jiǎn)單的更改:添加了 TenuredProfessor,這是從 Professor 中繼承的。

圖 5. 擴(kuò)展初始類層次結(jié)構(gòu)
圖 5. 擴(kuò)展初始類層次結(jié)構(gòu)

圖 6 顯示了一個(gè)更新過(guò)的持久性模型,用于將整個(gè)類層次結(jié)構(gòu)映射成一個(gè)數(shù)據(jù)實(shí)體。盡管很明顯,數(shù)據(jù)庫(kù)中的空間浪費(fèi)增加了,但請(qǐng)注意,按照這種策略操作,只需花非常小的代價(jià)就可以更新模型。

圖 6. 將擴(kuò)展的層次結(jié)構(gòu)映射成單一數(shù)據(jù)實(shí)體
圖 6. 將擴(kuò)展的層次結(jié)構(gòu)映射成單一數(shù)據(jù)實(shí)體

圖 7 顯示了將每個(gè)具體類映射成數(shù)據(jù)實(shí)體時(shí)的持久性模型。使用這個(gè)策略,雖然因?yàn)槲覀儚慕淌谔嵘浇K身教授,這樣對(duì)象和我們的關(guān)系就有了改變(學(xué)生變成教授),所以如何處理對(duì)象的這個(gè)問(wèn)題更復(fù)雜了,但我只需要添加一個(gè)新表。

圖 7. 將擴(kuò)展的層次結(jié)構(gòu)的具體類映射成數(shù)據(jù)實(shí)體
圖 7. 將擴(kuò)展的層次結(jié)構(gòu)的具體類映射成數(shù)據(jù)實(shí)體

圖 8 顯示了第三種映射策略的解決方案 -- 將單個(gè)類映射成單個(gè)數(shù)據(jù)實(shí)體。這需要我添加一個(gè)只包括 TenuredProfessor 類的新屬性的新表。這種方法的缺點(diǎn)是,要使用新類的實(shí)例,它需要好幾個(gè)數(shù)據(jù)庫(kù)訪問(wèn)。

圖 8. 將擴(kuò)展的層次結(jié)構(gòu)的所有類映射成數(shù)據(jù)實(shí)體
圖 8. 將擴(kuò)展的層次結(jié)構(gòu)的所有類映射成數(shù)據(jù)實(shí)體

要摒棄這樣一種觀點(diǎn),即這些辦法都不夠好;每種辦法都有其優(yōu)缺點(diǎn)。在下面的表 1 中對(duì)它們進(jìn)行比較。

表 1. 比較映射繼承的各種辦法

考慮因素
每個(gè)層次結(jié)構(gòu)一張表
每個(gè)具體類一張表
每個(gè)類一張表
專門報(bào)告
容易
中等
中等/困難
實(shí)現(xiàn)的難易程度
容易
中等
困難
數(shù)據(jù)訪問(wèn)的難易程度
容易
容易
中等/容易
耦合
非常高
數(shù)據(jù)訪問(wèn)速度
中等/快
對(duì)多態(tài)性的支持
中等

映射關(guān)聯(lián)、聚合和組成
不僅必須將對(duì)象映射到數(shù)據(jù)庫(kù)中,還必須將對(duì)象之間的關(guān)系進(jìn)行映射,這樣才能在以后進(jìn)行恢復(fù)。對(duì)象之間有四種類型的關(guān)系:繼承、關(guān)聯(lián)、聚合和組成。要有效地映射這些關(guān)系,必須理解它們之間的差異、如何實(shí)現(xiàn)一般的關(guān)系,以及如何實(shí)現(xiàn)特定的多對(duì)多關(guān)系。

關(guān)聯(lián)、聚合和組合之間的差異
從數(shù)據(jù)庫(kù)的角度看,關(guān)聯(lián)和聚合/組合關(guān)系之間的唯一不同是對(duì)象相互之間的綁定程度。對(duì)于聚合和組合,在數(shù)據(jù)庫(kù)中對(duì)整體所做的操作通常需要同時(shí)對(duì)部分進(jìn)行操作,而關(guān)聯(lián)就不是這樣。

在圖 9 中有三個(gè)類,其中兩個(gè)在它們之間有簡(jiǎn)單的關(guān)聯(lián)關(guān)系,有兩個(gè)共享聚合關(guān)系(實(shí)際上,組合可能是這種模型中更確切的說(shuō)法)。(有關(guān)關(guān)系的詳細(xì)信息,請(qǐng)參閱

圖 9. 關(guān)聯(lián)和聚合/組合之間的差異
圖 9. 關(guān)聯(lián)和聚合/組合之間的差異

在關(guān)系數(shù)據(jù)庫(kù)中實(shí)現(xiàn)關(guān)系
關(guān)系數(shù)據(jù)庫(kù)中的關(guān)系是通過(guò)使用外鍵來(lái)維護(hù)的。外鍵是在一張表中出現(xiàn)的一個(gè)或多個(gè)數(shù)據(jù)屬性;它可以是另一張表的鍵的一部分,或者干脆碰巧就是另一張表的鍵。外鍵可以讓您將一張表中的一行與另一張表中的一行相關(guān)起來(lái)。要實(shí)現(xiàn)一對(duì)一和一對(duì)多的關(guān)系,您只需要將一張表的鍵包括在另一張表中。

在圖 10 中有三張表,它們的鍵 (OID) 和外鍵用于在它們之間實(shí)現(xiàn)關(guān)系。首先,在 PositionEmployee 數(shù)據(jù)實(shí)體間有一個(gè)一對(duì)一的關(guān)聯(lián)。一對(duì)一關(guān)聯(lián)就是它的每個(gè)復(fù)合度的最大值都是 1 的這么一種關(guān)系。要實(shí)現(xiàn)這個(gè)關(guān)系,我在 Employee 數(shù)據(jù)實(shí)體中使用屬性 positionOID,Position 數(shù)據(jù)實(shí)體的鍵。因?yàn)殛P(guān)聯(lián)是單向的 -- employee 那些行知道它們的位置行,但反過(guò)來(lái)就不行 -- 所以我必須這么做。如果這是個(gè)雙向的關(guān)聯(lián),我還會(huì)在 Position 中添加一個(gè)名為 employeeOID 的外鍵。然后,使用相同的方法在 EmployeeTask 之間實(shí)現(xiàn)了多對(duì)一關(guān)聯(lián)(又稱為一對(duì)多關(guān)聯(lián)),唯一的不同是將外鍵放在了 Task 中,因?yàn)樗陉P(guān)系的“多”方。

圖 10. 簡(jiǎn)單人力資源數(shù)據(jù)庫(kù)的持久性模型。
圖 10. 簡(jiǎn)單人力資源數(shù)據(jù)庫(kù)的持久性模型

實(shí)現(xiàn)多對(duì)多關(guān)聯(lián)
要實(shí)現(xiàn)多對(duì)多關(guān)系,需要關(guān)聯(lián)表的概念,它是一種數(shù)據(jù)實(shí)體,唯一目標(biāo)是在關(guān)系數(shù)據(jù)庫(kù)中維護(hù)兩個(gè)或多個(gè)表之間的關(guān)聯(lián)。圖 10 中,在EmployeeBenefit 之間有一個(gè)多對(duì)多關(guān)系。圖 11 中,可以看到如何使用關(guān)聯(lián)表來(lái)實(shí)現(xiàn)多對(duì)多關(guān)系。在關(guān)系數(shù)據(jù)庫(kù)中,關(guān)聯(lián)表中包含的屬性傳統(tǒng)上是關(guān)系中涉及到的表中的鍵組合。關(guān)聯(lián)表的名稱通常是它所關(guān)聯(lián)的表的名稱組合,或者是它實(shí)現(xiàn)的關(guān)聯(lián)的名稱。在這種情況下,我選擇 EmployeeBenefit 而不是 BenefitEmployeehas,因?yàn)槲矣X(jué)得它可以更好地反映關(guān)聯(lián)的性質(zhì)。

圖 11. 在關(guān)系數(shù)據(jù)庫(kù)中實(shí)現(xiàn)多對(duì)多關(guān)系
圖 11. 在關(guān)系數(shù)據(jù)庫(kù)中實(shí)現(xiàn)多對(duì)多關(guān)系

看一下圖 11 中應(yīng)用程序的復(fù)合度。規(guī)則是,一旦引入了關(guān)聯(lián)表,復(fù)合度就“交叉”,如圖 12 所示。值為 ‘1‘ 的復(fù)合度總在外邊緣引入,如圖 11 和 12 中所示,以保留原始關(guān)聯(lián)的整體復(fù)合度。原始的關(guān)聯(lián)表明雇員有一種或多種福利,并且任何給定的福利都給予一個(gè)或多個(gè)雇員。在圖 11 中您可以看到,即使在有關(guān)聯(lián)表維護(hù)關(guān)聯(lián)的情況下仍然是這種情況。

圖 12. 關(guān)聯(lián)表簡(jiǎn)介
圖 12. 關(guān)聯(lián)表簡(jiǎn)介

有必要注明我選擇應(yīng)用構(gòu)造型“<<關(guān)聯(lián)表>>”而不是關(guān)聯(lián)類的說(shuō)明 -- 將關(guān)聯(lián)類與它所描述的關(guān)聯(lián)連接的虛線行 -- 出于兩個(gè)原因。首先,關(guān)聯(lián)表的目的是實(shí)現(xiàn)關(guān)聯(lián),而關(guān)聯(lián)類的目的是描述關(guān)聯(lián)。其次,圖 11 中采取的方法反映了為使用關(guān)系技術(shù)所需的實(shí)際實(shí)現(xiàn)策略。

結(jié)束語(yǔ)
在本文中,探索了對(duì)象-關(guān)系數(shù)據(jù)庫(kù)之間的映射的基礎(chǔ)。如果按照本文中描述的步驟操作,就可能方便地將對(duì)象成功存儲(chǔ)在關(guān)系數(shù)據(jù)庫(kù)中。如果有任何問(wèn)題,請(qǐng)發(fā)電子郵件給我,地址是 scott.ambler@,如果有興趣對(duì)持久性模型的 UML 概要提供建議,請(qǐng)放在關(guān)于持久性模型概要開(kāi)發(fā)的工作頁(yè)面上就可以了。

參考資料

關(guān)于作者

Scott W. Ambler 是 Ronin International 的總裁,這家公司是專門研究面向?qū)ο蟮能浖^(guò)程教學(xué)、體系結(jié)構(gòu)建模和 Enterprise JavaBeans (EJB) 開(kāi)發(fā)的咨詢企業(yè)。他創(chuàng)作或與他人合著了幾本有關(guān)面向?qū)ο箝_(kāi)發(fā)的書籍,包括最近發(fā)行的 The Object Primer 2nd Edition,該書詳細(xì)介紹了本文所概述的主題??梢酝ㄟ^(guò) scott.ambler@ 與他聯(lián)系。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多