| 導購 | 订阅 | 在线投稿
分享
 
 
 

使用UML設計數據庫應用(1)

來源:互聯網  2008-06-01 02:25:37  評論

1. 介紹

許多人認爲面向對象概念和關系型數據庫相互不一致,並且不能結合。事實上完全相反!經過靈活的使用,一個關系型數據庫能夠爲面向對象(OO)模型提供一套優秀的實現。同樣的模型能夠用來開發編程代碼和建立關系型數據庫結構。

關系型數據庫技術是意義深遠的、強大的,但它比許多開發商使你相信的要難得多。單個表是簡單易懂的、直觀的,但是要徹底了解由數以百計的表組成(這是常見的)的應用是相當困難的。這正是OO模型有用之處。

OO模型使你深入地、連貫地思考問題。OO模型提供一種問題的超結構(superstrUCture)的思考方式,然後該方式能夠用關系型數據庫的更低層的組成塊來實現。

本文章綜合地討論了關系型數據庫技術,而不是集中于特定的産品上。我們將不討論物理設計細節(例如存儲分配和物理聚集),因爲它們是依靠于産品的。

用關系型數據庫實現UML模型有兩個方面:映射結構(第2節)和映射功能(第3節)。第4節注解了面向對象到關系型數據庫的擴展。第5節總結本文章。

2. 結構映射到表

UML對象模型在本質上只是一個擴展的實體-關系(ER)模型[ii]。用來設計數據庫的ER模型的方式受到普遍接受,而我們將講述一種近似的但更強大的方式-使用UML對象模型。OO模型的主要優勢在于編程和數據庫使用相同的模型工作。而且,作爲考慮功能性的一種方式(第3節),我們強調OO模型的導航。這一節顯示如何實現UML對象模型的主要構造。

2.1 標識(identity)

實現對象模型的第一步是處理標識。我們從定義幾個術語開始。

候選鍵(candidate key)是一個或多個屬性的組合,它唯一地確定某個表裏的記錄。一個候選鍵裏的屬性集必須是最小化的;除非破壞唯一性,否則屬性不能從候選鍵刪除。候選鍵裏的屬性不能爲空。

主鍵(PRimary key)是一個特定選定的候選鍵,用來優先地參考記錄。

外鍵(foreign key)是一個候選鍵的參考。外鍵必須包括每個要素屬性的一個值,或者它必須全部爲空。外鍵用來實現關聯和泛化。 正常地你應該爲每個表定義一個主鍵,盡管偶然有例外。我們強烈建議所有的外鍵都只指向主鍵而不是其它的候選鍵。

定義主鍵有兩種基本的方法:

基于存在的標識。你應該爲每個類表加一個對象標識符屬性,並將它設爲主鍵。每個關聯表的主鍵包括一個或更多的相關類的標識符。基于存在的標識符有作爲單獨屬性的優勢,占位小且大小相同。只要你的關系型數據庫治理系統(RDBMS)支持,基于存在的標識符就沒有性能的劣勢。(多數RDBMS提供有效的基于存在的標識符的分配順序號碼。)唯一的劣勢是基于存在的標識符在維護時內沒有固有的意義。

基于值的標識。一些真實世界的屬性的組合確定了每個對象。基于值的標識有不同的優勢。主鍵對于用戶有固有的意義,輕易進行調試和數據庫維護。在另一面,基于值的主鍵很難改變。一個主鍵的改變需要傳播到許多外鍵。而一些對象沒有自然的真實世界裏的標識符。

我們推薦你在超過30個類的RDBMS應用裏使用基于存在的標識。基于存在和基于值的標識都是所有RDBMS應用的可行選項。

2.2 域(屬性類型)

屬性類型是UML術語,對應于數據庫著作裏的域的術語。比起直接用數據類型,域提升到更一致的設計,並便利了應用的定位。

簡單域很輕易實現。你僅僅要定義相應的數據類型和大小。並且每個用了域的屬性,你都必須爲每個域約束加入一條SQL檢查子句。簡單域的一些例子是:名字(name),長字符(longString)和電話號碼(phone-Number)。

一個枚舉域把一個屬性限制在一系列的值裏。枚舉域比簡單域實現起來更複雜,圖1顯示了四個方法。

圖1 枚舉的實現方法。

實現方法

優勢

劣勢

建議

枚舉字符。定義一條SQL檢查約束,把該枚舉限制在答應的值裏。

簡單。受控的方便搜索的詞彙表。

大的枚舉難以使用檢查。約束難以編碼。

我們正常地選擇。

每個枚舉值一個標記。爲每個枚舉的值定義一個布爾型屬性。

回避命名的難處。

冗長 - 每個值一個屬性。

當枚舉值不是互相排斥的並且多個值可能同時地應用時使用。

枚舉表。把枚舉定義存儲到一個表裏。不是每個枚舉一個表,也不是所有的枚舉一個表。

高效地處理大的枚舉。不用改變應用的代碼就可以定義新的枚舉值

偶然使用時很麻煩。必須編寫通用的軟件來閱讀枚舉表和加強值。

適合大的枚舉和沒有結尾(open-ended)的枚舉。

枚舉編碼。把枚舉值編碼作爲有序的數字。

節省磁盤空間。有助于用多種語言處理。

大大地複雜化了維護和調試。

避免使用,除非你要用多種語言處理。

2.3 類

正常情況下,我們把每個類映射爲一個表,每個屬性映射爲一個列。你可能因一個已産生的標識符(基于存在的標識符)、隱藏的關聯(第2.4節)和通用鑒別器(第2.5節)需要一些另外的列。

2.4 關聯

現在我們討論關聯的實現。我們已經把我們的陳述分爲建議的映射(我們正常使用的映射),可選的映射(我們偶然使用的映射)和不鼓勵的映射(我們碰到的應該避免的錯誤)。我們所有的例子都采用基于存在的標識。

2.4.1 建議的映射

多對多關聯。用一個單獨的表(圖2)來實現一個多對多關聯。關聯的主鍵是每個類的主鍵的合並。那些省略號(...)表示在模型裏沒有顯示出來的屬性。主鍵用黑體字體顯示。

一對多關聯。把一個外鍵隱藏在「多」表(圖3)。角色名字成爲外鍵屬性名字的一部分。

零或一對一關聯。把外鍵隱藏在「零或一」表(圖4)。

其它一對一關聯。把外鍵隱藏在任一表裏。 圖2 建議的實現:單獨的多對多關聯表。

使用UML設計數據庫應用(1)

QQread.com

推出各大專業服務器評測 linux服務器的安全性能

SUN服務器

HP服務器

DELL服務器

IBM服務器

聯想服務器

浪潮服務器

曙光服務器

同方服務器

華碩服務器

寶德服務器

圖3 建議的實現:隱藏的一對多關聯。

使用UML設計數據庫應用(1)

圖4 建議的實現:隱藏的零或一對一關聯。

使用UML設計數據庫應用(1)

2.4.2 可選的映射

正常情況下我們使用建議的映射。但有些偶然的情況,可選的映射更合適。

單獨的表。你也可以用單獨的表(圖5)來實現一對多和一對一關聯。單獨的表給了你更統一的設計和更大的擴展性。無論如何,單獨的關聯表打壞了數據庫,並增加了表的數量。此外,單獨的關聯表不能強迫一個更低的多重性限度爲「一」。 2.4.3 不鼓勵的映射

我們已經注重到有些開發者選擇有缺陷的映射。我們要注重避免這些映射。

合並。不要合並多個類,不要把關聯強制成爲一個單獨的表(圖6)。這樣減少了表的數量,但會幹擾第三範式。

兩次隱藏一對一關聯。不要把一個一對一關聯隱藏兩次,每次隱藏在一個類裏(圖7)。這是多余的,無助于性能。

相同的屬性。不要用相同的屬性來實現多個關聯角色(圖8)。相同的屬性使編程複雜,降低了擴展性。 圖5 可選的實現:單獨的一對x關聯表。

使用UML設計數據庫應用(1)
>

圖6 不鼓勵的實現:類的合並。

使用UML設計數據庫應用(1)
>

圖7 不鼓勵的實現:兩次隱藏的一對一鼓勵。

使用UML設計數據庫應用(1)
>

圖8 不鼓勵的實現:相同的屬性。

使用UML設計數據庫應用(1)
>2.5 泛化

現在我們討論泛化。我們這裏只論述單個繼續。

2.5.1 建議的映射

最簡單的方法是只映射超類和每個子類爲一個表。所有的表共享一個共同的主鍵。應用必須執行子類的劃分,因爲RDBMS並不能執行。(關于後者的詳盡的描述,請參閱第4節。)

單獨的表。映射超類和每個子類爲一個表(圖9)。所有的表共享一個共同的主鍵。鑒別器指出每個子類記錄的適當的超類表。 圖9 建議的實現:分開的超類和子類表。

使用UML設計數據庫應用(1)

2.5.2 可選的映射

泛化有幾個可選的映射。

消除。你可以優化除去那些除了主鍵外沒有別的屬性的類(圖10)。這樣減少了表的數量,但提供更少的正規實現。

減少超類屬性。你可以除去超類表並把超類屬性複制到每個子類(圖11)。這樣可以有描述每個對象爲一個表的優勢。無論如何,它將引起數據庫結構的冗余,你查找一個對象時可能需要搜索多個子類表。

增加子類屬性。作爲第三個可選項,你可以除去子類表並存儲所有的子類屬性到超類表裏(圖12)。這樣用一個表描述每個對象,但幹擾了第二範式。 圖10 可選的實現:消除不必要的子類表

使用UML設計數據庫應用(1)
>

圖11 可選的實現:減少超類屬性。

使用UML設計數據庫應用(1)
>

圖12 可選的實現:增加子類屬性。

使用UML設計數據庫應用(1)
>2.6 參考完整性

一旦你已經建立了表,你就應該定義參考完整性動作來明確對象模型的意義。(不要使用SQL觸發器來實現參考完整性!)假如你使用基于存在的標識,你將不需要傳播更新的結果。我們建議以下對刪除的參考完整性方針:

泛化。級聯從泛化實現中産生的外鍵的刪除。

隱藏的關聯,最小多重性爲零。正常地把外鍵設爲空,但有時候你可能要禁止刪除。

隱藏的關聯,最小多重性爲空。你可以級聯一個刪除的結果或者禁止該刪除。

關聯表。正常地我們對關聯表裏的記錄進行級聯刪除。可是,有時候我們禁止一個刪除。

我們已經簡要地論及參考完整性,因爲它是個高級話題。參考文獻[iii]有更多的解釋和例子。

QQread.com

推出各大專業服務器評測 Linux服務器的安全性能

SUN服務器

HP服務器

DELL服務器

IBM服務器

聯想服務器

浪潮服務器

曙光服務器

同方服務器

華碩服務器

寶德服務器

2.7 索引

實現數據庫結構的最後的一步是加入索引來調整數據庫性能。正常地,你應該爲每個主鍵和候選鍵定義一個唯一的索引。(多數RDBMS作爲SQL主鍵和候選鍵約束的副作用來建立唯一的索引。)你也應該爲每個被主鍵或候選鍵所約束的外鍵建立一個索引。

我們強調索引的重要性。外鍵和主鍵的索引使在對象模型裏能快速地遍曆是不容懷疑的。你必須包括這些索引,否則你將使用戶感到灰心。你應該在你的數據庫開始設計階段裏加入索引,因爲它們很輕易加入並且也沒有什麽好理由推遲加入。

數據庫治理員(DBA)可能爲經常請求的查詢定義了額外的索引。DBA也可能采用産品相關的調整性能的機制。

2.8 範式

範式是關系型數據庫設計的提高數據一致性的有效方法。我們的書3討論了範式,但我們關于這個問題卻說錯了。我們將利用這篇文章的機會來澄清我們的觀點。假如你不熟悉範式你可以跳過這節。我們的說明是針對關系型設計人員,他們正在嘗試用面向對象適應他們原有的技能。

範式是正確設計關系型數據庫的精確的原則。同樣地,它們與使用了什麽開發技術是無關的 - 基于屬性的設計、基于實體的設計、面向對象設計或其它什麽。

過去使用基于屬性設計的方法,開發人員不得不非常注重範式;範式提供了分組數據的根據。相反地,範式對于基于面向對象(或基于實體)的開發不是很重要。假如你采用OO方法並且你的模型經過很好的構思,那你就正在把數據組織成爲有意義的單位,也在本質上滿足了範式的規定。假如你願意,你仍能夠檢查範式,但這樣的檢查是不必要的。

2.9 摘要

圖13總結了我們已經陳述的映射規則。這些映射規則的完整例子,包括一個UML對象模型,能夠在這篇完整的擴展版本裏找到(Adobe Acrobat PDF文件)。

概念

對象模型構造

推薦的RDBMS映射

簡單域

映射爲一個數據類型和大小

標識符

用RDBMS順序號

枚舉

通常儲存爲一個字符串

映射每個類爲一個表

關聯

多對多關聯

單獨的表

一對多關聯

隱藏的外鍵

一對一關聯

泛化

分開超類表和子類表

圖13 推薦的映射規則的摘要。

3. 把功能映射到SQL命令

對象模型爲數據庫應用提供三種主要的用途。

結構。對象模型指明數據庫結構。我們已經在第二節探討了這個方面。

約束。對象模型也指明了能存儲的數據上的重要的約束。相匹配的實現必須爲迎合這些約束而努力。我們的映射規則的處理方法以及第二節裏的參考完整性指出了許多約束。(本文沒有論及的另外的UML構造,能獲取更多的約束。)

潛在估算。一個對象模型指明潛在估算;它是關于引起哪些查詢和如何公式化的藍圖。第三節將簡要地闡明第三個目的。 對象模型不僅僅是被動的數據結構,相反它們能夠幫助你思考一個應用的功能。你可以根據遍曆一個對象模型說出它的許多功能。例如,根據我們對一個模型檢查用例時的遍曆,我們進行思考。這強調對象模型的估算能力對于RDBMS應用是非凡重要的,因爲遍曆表達式可以直接映射到SQL代碼。

UML對象約束語言(Object Constraint Language,OCL)有助于表達遍曆。點符號導航從對象到對象和對象到屬性,方括號表示對象集合的過濾器。我們加入冒號(:)操作符來表示泛化的遍曆;因爲我們正常地用多個表來實現一個泛化繼續,清楚的遍曆很有用。

圖14裏的遍曆表達式例子是基于我們創建的UML對象模型上的(請參閱本文的擴展版本(Adobe Acrobat PDF文件)),我們把它們映射爲SQL代碼。我們用冒號開始SQL編程變量。

遍曆表達式

含義

SQL代碼

anAirline.Emploee

給定的一條航線,找出相應的員工。

SELECT employeeID FROM Employee WHERE arilineID = :anAirline;

anAirline.Employee.name

給定的一條航線,找出相應的員工的名字。

SELECT name FROM Employee WHERE airlineID = :anAirline;

anAirline.Flight

[getMonth(date)==aMonth].pilot

找出在某個給定的月份裏爲一條航行飛行的機師。

SELECT pilotID FROM Flight WHERE airlineID = :anAirline AND GetMonth(date) = :aMonth;

anAirline.Flight

[getMonth(date)==aMonth].pilot[flightRating==aFlightRating]

找出在某個給定的月份裏爲一條航線飛行的在一個給定的飛行等級裏的機師。

SELECT P.pilotID FROM Flight F, Pilot P WHERE F.airlineID = :anAirline AND getMonth(F.date) = :aMonth AND F.pilotID = P.pilotID AND P.flightRating = :aFlightRating;

aFlight.copilot:Employee.name

爲一次飛行找出副機師的名字。

SELECT E.name FROM Flight F, Pilot P, Employee E WHERE F.flightID = :aFlight AND F.copilotID = P.pilotID AND P.pilotID = E.employeeID;

圖14 對象模型遍曆和SQL代碼的例子。

QQread.com

推出各大專業服務器評測 Linux服務器的安全性能

SUN服務器

HP服務器

DELL服務器

IBM服務器

聯想服務器

浪潮服務器

曙光服務器

同方服務器

華碩服務器

寶德服務器

4. RDBMS的OO擴展

數據庫團體對RDBMS的OO擴展有愛好。産品和SQL標准正嘗試加入到OO擴展裏。我們將簡要地陳述一下這個技術的方向。

抽象數據類型(ADT)。這是個好主意,擴展RDBMS的能力。開發商爲這個技術使用了許多名字,例如Oracle cartridge和Informix data blades。ADT的缺點是它們把你緊緊綁在特定的一個開發商上;ADT的範疇超越了SQL標准。因此,你應該只在ADT的好處很明顯的時候才使用。

在關于ADT如何適合數據庫開發的著作裏有一些混亂。假如你使用OMT開發過程,你能夠用屬性實現簡單域,用ADT實現複雜域。你仍應該用表實現類。

SQL3指針。最新的SQL標准的版本,SQL3,加入了作爲一種數據類型的指針符號。顯然,其意圖是支持導航和面向對象。我們對于SQL3指針最友善的評語是,它們是嫁接的,是可以忽略的。更深入的批評是,指針在理論上是荒謬的,增加了複雜性,又沒有擴展SQL的表達能力。CJ Date在上次的九月對象/關系型會議上雄辯地討論了這一點[iv]。

好了,那麽我們冷淡地對待抽象數據類型和SQL指針的指責。但我們相當喜歡面向對象技術和關系型數據庫。有兩個爲RDBMS的擴展可以使它們更輕易用于OO技術。我們將很樂意看到RDBMS開發商把這些能力加入到他們的産品中。

擴展的參考完整性動作來支持泛化。當前的參考完整性機制是單向的。爲了完全支持泛化,我們需要一個雙向的機制。這樣,一條超類記錄就可以依靠一條子類記錄。並且,一條子類記錄就可以依靠一條超類記錄。我們通過例子可以最好地解釋這點。 圖15摘錄于我們的在參考文獻3的財務案例學習。我們用資産超類來統一某些沒有顯示在摘錄裏的通用的數據和功能。一項資産可以是一支股票或股票期權。一支股票可以有許多它的股票期權。例如,IBM股票可以有許多寫明達到價格和過期日期的期權。

使用UML設計數據庫應用(1)
>

圖15 參考完整性和泛化的例子。

我們推薦的泛化實現是單獨的表 - 映射該超類和每個子類爲一個表。然後,我們就可以使用參考完整性使股票期權和股票的記錄依靠于資産。一個資産記錄的刪除級聯到相應的子類記錄、股票期權或股票的刪除上。我們也能夠定義一個參考完整性動作,這樣一個股票的刪除就級聯到關聯的股票期權記錄的刪除。

現在問題如下:假如我們刪除的一項資産是一支股票,資産記錄的刪除級聯到引起股票記錄的刪除。隨後,股票記錄的刪除級聯引起所有股票期權記錄的刪除。但現在參考完整性使我們失敗了:一條股票期權記錄的刪除並不引起一項資産記錄的刪除。刪除級聯只能從超類走到子類。爲了完全的行爲,級聯應該雙向地走下去。

當前有用的參考完整性的工作是做更多的編程(也即做更多的工作和承擔更多的故障風險)。在我們的案例學習的實現裏,用戶隨時要刪除一項是股票的資産,我們不得不書寫額外的代碼來首先檢查關聯股票期權的存在性,然後刪除它們。

支持交叉表的記錄劃分。單繼續(泛化的最常見方式)的含義是一個超類的每個實例都是用最多一個子類來例示。現在的RDBMS不能輕易地加強這個約束。例如,沒有什麽防止下面的情形。一支股票可以用ID18加入到資産表,用ID18加入到股票表,並且也可以用ID18加入到股票期權表。再一次地,我們爲了確信行爲的完整,不得不作額外的編程,而不是寫一個簡單的聲明約束。 5. 結論

本文陳述了用關系型數據庫實現UML模型的快速的概觀。我們希望本文向你演示的技術是十分適用的。一個練習有素的開發人員能夠用關系型數據庫預備一套優秀的OO模型的實現。假如你要關于實現機制的更多的細節,參考3有另外的信息,並且也覆蓋了我們沒有在這裏討論的一些高級模型建模結構。

關于作者

Michael Blana是紐約Schenectady的通用電氣研發部的畢業生(譯者按:這是作者幽默的說法,意思是他已經跳槽了)。在過去的五年裏,他已經成爲面向對象技術、建模、數據庫設計和逆向工程領域的獨立的産業顧問。Blaha博士是多篇論文、五個專利和兩本書的作者。可以通過www.omtassociates.com或blaha@acm.org和他聯系。

William Premerlani從1975年開始就在通用電氣研發部供職。他的主要研究愛好在軟件工程、元建模(metamodeling)、數據庫技術和複雜工程應用等領域。Premerlani博士是許多論文、二十五個專利和兩本書的作者。通過premerlani@acm.org和他聯系。

參考資料

[i]Michael Blaha and William Premerlani. Object-Oriented Design of Database applications. Rose Architect 1,2 (Winter, 1999).

[ii] PPS Chen. The Entity-Relationship model - toward a unified view of data. ACM Transactions on Database Systems1, 1 (March 1976).

[iii] Michael Blaha and William Premerlani. Object-Oriented Modeling and Design for Database Applications, Prentice Hall, Englewood Cliffs, New Jersey, 1998.

[iv] CJ Date. Don't mix pointers and relations! Presentation at Third Annual Object/Relational Summit sponsored by Miller Freeman, Washington D.C., September 16-19, 1998.

(責任編輯:銘銘)

1. 介紹 許多人認爲面向對象概念和關系型數據庫相互不一致,並且不能結合。事實上完全相反!經過靈活的使用,一個關系型數據庫能夠爲面向對象(OO)模型提供一套優秀的實現。同樣的模型能夠用來開發編程代碼和建立關系型數據庫結構。 關系型數據庫技術是意義深遠的、強大的,但它比許多開發商使你相信的要難得多。單個表是簡單易懂的、直觀的,但是要徹底了解由數以百計的表組成(這是常見的)的應用是相當困難的。這正是OO模型有用之處。 OO模型使你深入地、連貫地思考問題。OO模型提供一種問題的超結構(superstrUCture)的思考方式,然後該方式能夠用關系型數據庫的更低層的組成塊來實現。 本文章綜合地討論了關系型數據庫技術,而不是集中于特定的産品上。我們將不討論物理設計細節(例如存儲分配和物理聚集),因爲它們是依靠于産品的。 用關系型數據庫實現UML模型有兩個方面:映射結構(第2節)和映射功能(第3節)。第4節注解了面向對象到關系型數據庫的擴展。第5節總結本文章。 2. 結構映射到表 UML對象模型在本質上只是一個擴展的實體-關系(ER)模型[ii]。用來設計數據庫的ER模型的方式受到普遍接受,而我們將講述一種近似的但更強大的方式-使用UML對象模型。OO模型的主要優勢在于編程和數據庫使用相同的模型工作。而且,作爲考慮功能性的一種方式(第3節),我們強調OO模型的導航。這一節顯示如何實現UML對象模型的主要構造。 2.1 標識(identity) 實現對象模型的第一步是處理標識。我們從定義幾個術語開始。 候選鍵(candidate key)是一個或多個屬性的組合,它唯一地確定某個表裏的記錄。一個候選鍵裏的屬性集必須是最小化的;除非破壞唯一性,否則屬性不能從候選鍵刪除。候選鍵裏的屬性不能爲空。 主鍵(PRimary key)是一個特定選定的候選鍵,用來優先地參考記錄。 外鍵(foreign key)是一個候選鍵的參考。外鍵必須包括每個要素屬性的一個值,或者它必須全部爲空。外鍵用來實現關聯和泛化。 正常地你應該爲每個表定義一個主鍵,盡管偶然有例外。我們強烈建議所有的外鍵都只指向主鍵而不是其它的候選鍵。 定義主鍵有兩種基本的方法: 基于存在的標識。你應該爲每個類表加一個對象標識符屬性,並將它設爲主鍵。每個關聯表的主鍵包括一個或更多的相關類的標識符。基于存在的標識符有作爲單獨屬性的優勢,占位小且大小相同。只要你的關系型數據庫治理系統(RDBMS)支持,基于存在的標識符就沒有性能的劣勢。(多數RDBMS提供有效的基于存在的標識符的分配順序號碼。)唯一的劣勢是基于存在的標識符在維護時內沒有固有的意義。 基于值的標識。一些真實世界的屬性的組合確定了每個對象。基于值的標識有不同的優勢。主鍵對于用戶有固有的意義,輕易進行調試和數據庫維護。在另一面,基于值的主鍵很難改變。一個主鍵的改變需要傳播到許多外鍵。而一些對象沒有自然的真實世界裏的標識符。 我們推薦你在超過30個類的RDBMS應用裏使用基于存在的標識。基于存在和基于值的標識都是所有RDBMS應用的可行選項。 2.2 域(屬性類型) 屬性類型是UML術語,對應于數據庫著作裏的域的術語。比起直接用數據類型,域提升到更一致的設計,並便利了應用的定位。 簡單域很輕易實現。你僅僅要定義相應的數據類型和大小。並且每個用了域的屬性,你都必須爲每個域約束加入一條SQL檢查子句。簡單域的一些例子是:名字(name),長字符(longString)和電話號碼(phone-Number)。 一個枚舉域把一個屬性限制在一系列的值裏。枚舉域比簡單域實現起來更複雜,圖1顯示了四個方法。 圖1 枚舉的實現方法。 實現方法 優勢 劣勢 建議 枚舉字符。定義一條SQL檢查約束,把該枚舉限制在答應的值裏。 簡單。受控的方便搜索的詞彙表。 大的枚舉難以使用檢查。約束難以編碼。 我們正常地選擇。 每個枚舉值一個標記。爲每個枚舉的值定義一個布爾型屬性。 回避命名的難處。 冗長 - 每個值一個屬性。 當枚舉值不是互相排斥的並且多個值可能同時地應用時使用。 枚舉表。把枚舉定義存儲到一個表裏。不是每個枚舉一個表,也不是所有的枚舉一個表。 高效地處理大的枚舉。不用改變應用的代碼就可以定義新的枚舉值 偶然使用時很麻煩。必須編寫通用的軟件來閱讀枚舉表和加強值。 適合大的枚舉和沒有結尾(open-ended)的枚舉。 枚舉編碼。把枚舉值編碼作爲有序的數字。 節省磁盤空間。有助于用多種語言處理。 大大地複雜化了維護和調試。 避免使用,除非你要用多種語言處理。 2.3 類 正常情況下,我們把每個類映射爲一個表,每個屬性映射爲一個列。你可能因一個已産生的標識符(基于存在的標識符)、隱藏的關聯(第2.4節)和通用鑒別器(第2.5節)需要一些另外的列。 2.4 關聯 現在我們討論關聯的實現。我們已經把我們的陳述分爲建議的映射(我們正常使用的映射),可選的映射(我們偶然使用的映射)和不鼓勵的映射(我們碰到的應該避免的錯誤)。我們所有的例子都采用基于存在的標識。 2.4.1 建議的映射 多對多關聯。用一個單獨的表(圖2)來實現一個多對多關聯。關聯的主鍵是每個類的主鍵的合並。那些省略號(...)表示在模型裏沒有顯示出來的屬性。主鍵用黑體字體顯示。 一對多關聯。把一個外鍵隱藏在「多」表(圖3)。角色名字成爲外鍵屬性名字的一部分。 零或一對一關聯。把外鍵隱藏在「零或一」表(圖4)。 其它一對一關聯。把外鍵隱藏在任一表裏。 圖2 建議的實現:單獨的多對多關聯表。 [url=/bbs/detail_1785878.html][img]http://image.wangchao.net.cn/it/1323421608001.gif[/img][/url] QQread.com 推出各大專業服務器評測 linux服務器的安全性能 SUN服務器 HP服務器 DELL服務器 IBM服務器 聯想服務器 浪潮服務器 曙光服務器 同方服務器 華碩服務器 寶德服務器   圖3 建議的實現:隱藏的一對多關聯。 [url=/bbs/detail_1785878.html][img]http://image.wangchao.net.cn/it/1323421608089.gif[/img][/url] 圖4 建議的實現:隱藏的零或一對一關聯。 [url=/bbs/detail_1785878.html][img]http://image.wangchao.net.cn/it/1323421608217.gif[/img][/url] 2.4.2 可選的映射 正常情況下我們使用建議的映射。但有些偶然的情況,可選的映射更合適。 單獨的表。你也可以用單獨的表(圖5)來實現一對多和一對一關聯。單獨的表給了你更統一的設計和更大的擴展性。無論如何,單獨的關聯表打壞了數據庫,並增加了表的數量。此外,單獨的關聯表不能強迫一個更低的多重性限度爲「一」。 2.4.3 不鼓勵的映射 我們已經注重到有些開發者選擇有缺陷的映射。我們要注重避免這些映射。 合並。不要合並多個類,不要把關聯強制成爲一個單獨的表(圖6)。這樣減少了表的數量,但會幹擾第三範式。 兩次隱藏一對一關聯。不要把一個一對一關聯隱藏兩次,每次隱藏在一個類裏(圖7)。這是多余的,無助于性能。 相同的屬性。不要用相同的屬性來實現多個關聯角色(圖8)。相同的屬性使編程複雜,降低了擴展性。 圖5 可選的實現:單獨的一對x關聯表。 [url=/bbs/detail_1785878.html][img]http://image.wangchao.net.cn/it/1323421608336.gif[/img][/url]> 圖6 不鼓勵的實現:類的合並。 [url=/bbs/detail_1785878.html][img]http://image.wangchao.net.cn/it/1323421608420.gif[/img][/url]> 圖7 不鼓勵的實現:兩次隱藏的一對一鼓勵。 [url=/bbs/detail_1785878.html][img]http://image.wangchao.net.cn/it/1323421608732.gif[/img][/url]> 圖8 不鼓勵的實現:相同的屬性。 [url=/bbs/detail_1785878.html][img]http://image.wangchao.net.cn/it/1323421608815.gif[/img][/url]>2.5 泛化 現在我們討論泛化。我們這裏只論述單個繼續。 2.5.1 建議的映射 最簡單的方法是只映射超類和每個子類爲一個表。所有的表共享一個共同的主鍵。應用必須執行子類的劃分,因爲RDBMS並不能執行。(關于後者的詳盡的描述,請參閱第4節。) 單獨的表。映射超類和每個子類爲一個表(圖9)。所有的表共享一個共同的主鍵。鑒別器指出每個子類記錄的適當的超類表。 圖9 建議的實現:分開的超類和子類表。 [url=/bbs/detail_1785878.html][img]http://image.wangchao.net.cn/it/1323421608890.gif[/img][/url] 2.5.2 可選的映射 泛化有幾個可選的映射。 消除。你可以優化除去那些除了主鍵外沒有別的屬性的類(圖10)。這樣減少了表的數量,但提供更少的正規實現。 減少超類屬性。你可以除去超類表並把超類屬性複制到每個子類(圖11)。這樣可以有描述每個對象爲一個表的優勢。無論如何,它將引起數據庫結構的冗余,你查找一個對象時可能需要搜索多個子類表。 增加子類屬性。作爲第三個可選項,你可以除去子類表並存儲所有的子類屬性到超類表裏(圖12)。這樣用一個表描述每個對象,但幹擾了第二範式。 圖10 可選的實現:消除不必要的子類表 [url=/bbs/detail_1785878.html][img]http://image.wangchao.net.cn/it/1323421609008.gif[/img][/url]> 圖11 可選的實現:減少超類屬性。 [url=/bbs/detail_1785878.html][img]http://image.wangchao.net.cn/it/1323421609071.gif[/img][/url]> 圖12 可選的實現:增加子類屬性。 [url=/bbs/detail_1785878.html][img]http://image.wangchao.net.cn/it/1323421609165.gif[/img][/url]>2.6 參考完整性 一旦你已經建立了表,你就應該定義參考完整性動作來明確對象模型的意義。(不要使用SQL觸發器來實現參考完整性!)假如你使用基于存在的標識,你將不需要傳播更新的結果。我們建議以下對刪除的參考完整性方針: 泛化。級聯從泛化實現中産生的外鍵的刪除。 隱藏的關聯,最小多重性爲零。正常地把外鍵設爲空,但有時候你可能要禁止刪除。 隱藏的關聯,最小多重性爲空。你可以級聯一個刪除的結果或者禁止該刪除。 關聯表。正常地我們對關聯表裏的記錄進行級聯刪除。可是,有時候我們禁止一個刪除。 我們已經簡要地論及參考完整性,因爲它是個高級話題。參考文獻[iii]有更多的解釋和例子。 QQread.com 推出各大專業服務器評測 Linux服務器的安全性能 SUN服務器 HP服務器 DELL服務器 IBM服務器 聯想服務器 浪潮服務器 曙光服務器 同方服務器 華碩服務器 寶德服務器 2.7 索引 實現數據庫結構的最後的一步是加入索引來調整數據庫性能。正常地,你應該爲每個主鍵和候選鍵定義一個唯一的索引。(多數RDBMS作爲SQL主鍵和候選鍵約束的副作用來建立唯一的索引。)你也應該爲每個被主鍵或候選鍵所約束的外鍵建立一個索引。 我們強調索引的重要性。外鍵和主鍵的索引使在對象模型裏能快速地遍曆是不容懷疑的。你必須包括這些索引,否則你將使用戶感到灰心。你應該在你的數據庫開始設計階段裏加入索引,因爲它們很輕易加入並且也沒有什麽好理由推遲加入。 數據庫治理員(DBA)可能爲經常請求的查詢定義了額外的索引。DBA也可能采用産品相關的調整性能的機制。 2.8 範式 範式是關系型數據庫設計的提高數據一致性的有效方法。我們的書3討論了範式,但我們關于這個問題卻說錯了。我們將利用這篇文章的機會來澄清我們的觀點。假如你不熟悉範式你可以跳過這節。我們的說明是針對關系型設計人員,他們正在嘗試用面向對象適應他們原有的技能。 範式是正確設計關系型數據庫的精確的原則。同樣地,它們與使用了什麽開發技術是無關的 - 基于屬性的設計、基于實體的設計、面向對象設計或其它什麽。 過去使用基于屬性設計的方法,開發人員不得不非常注重範式;範式提供了分組數據的根據。相反地,範式對于基于面向對象(或基于實體)的開發不是很重要。假如你采用OO方法並且你的模型經過很好的構思,那你就正在把數據組織成爲有意義的單位,也在本質上滿足了範式的規定。假如你願意,你仍能夠檢查範式,但這樣的檢查是不必要的。 2.9 摘要 圖13總結了我們已經陳述的映射規則。這些映射規則的完整例子,包括一個UML對象模型,能夠在這篇完整的擴展版本裏找到(Adobe Acrobat PDF文件)。 概念 對象模型構造 推薦的RDBMS映射 域 簡單域 映射爲一個數據類型和大小 標識符 用RDBMS順序號 枚舉 通常儲存爲一個字符串 類 類 映射每個類爲一個表 關聯 多對多關聯 單獨的表 一對多關聯 隱藏的外鍵 一對一關聯 泛化   分開超類表和子類表 圖13 推薦的映射規則的摘要。 3. 把功能映射到SQL命令 對象模型爲數據庫應用提供三種主要的用途。 結構。對象模型指明數據庫結構。我們已經在第二節探討了這個方面。 約束。對象模型也指明了能存儲的數據上的重要的約束。相匹配的實現必須爲迎合這些約束而努力。我們的映射規則的處理方法以及第二節裏的參考完整性指出了許多約束。(本文沒有論及的另外的UML構造,能獲取更多的約束。) 潛在估算。一個對象模型指明潛在估算;它是關于引起哪些查詢和如何公式化的藍圖。第三節將簡要地闡明第三個目的。 對象模型不僅僅是被動的數據結構,相反它們能夠幫助你思考一個應用的功能。你可以根據遍曆一個對象模型說出它的許多功能。例如,根據我們對一個模型檢查用例時的遍曆,我們進行思考。這強調對象模型的估算能力對于RDBMS應用是非凡重要的,因爲遍曆表達式可以直接映射到SQL代碼。 UML對象約束語言(Object Constraint Language,OCL)有助于表達遍曆。點符號導航從對象到對象和對象到屬性,方括號表示對象集合的過濾器。我們加入冒號(:)操作符來表示泛化的遍曆;因爲我們正常地用多個表來實現一個泛化繼續,清楚的遍曆很有用。 圖14裏的遍曆表達式例子是基于我們創建的UML對象模型上的(請參閱本文的擴展版本(Adobe Acrobat PDF文件)),我們把它們映射爲SQL代碼。我們用冒號開始SQL編程變量。 遍曆表達式 含義 SQL代碼 anAirline.Emploee 給定的一條航線,找出相應的員工。 SELECT employeeID FROM Employee WHERE arilineID = :anAirline; anAirline.Employee.name 給定的一條航線,找出相應的員工的名字。 SELECT name FROM Employee WHERE airlineID = :anAirline; anAirline.Flight [getMonth(date)==aMonth].pilot 找出在某個給定的月份裏爲一條航行飛行的機師。 SELECT pilotID FROM Flight WHERE airlineID = :anAirline AND GetMonth(date) = :aMonth; anAirline.Flight [getMonth(date)==aMonth].pilot[flightRating==aFlightRating] 找出在某個給定的月份裏爲一條航線飛行的在一個給定的飛行等級裏的機師。 SELECT P.pilotID FROM Flight F, Pilot P WHERE F.airlineID = :anAirline AND getMonth(F.date) = :aMonth AND F.pilotID = P.pilotID AND P.flightRating = :aFlightRating; aFlight.copilot:Employee.name 爲一次飛行找出副機師的名字。 SELECT E.name FROM Flight F, Pilot P, Employee E WHERE F.flightID = :aFlight AND F.copilotID = P.pilotID AND P.pilotID = E.employeeID; 圖14 對象模型遍曆和SQL代碼的例子。 QQread.com 推出各大專業服務器評測 Linux服務器的安全性能 SUN服務器 HP服務器 DELL服務器 IBM服務器 聯想服務器 浪潮服務器 曙光服務器 同方服務器 華碩服務器 寶德服務器 4. RDBMS的OO擴展 數據庫團體對RDBMS的OO擴展有愛好。産品和SQL標准正嘗試加入到OO擴展裏。我們將簡要地陳述一下這個技術的方向。 抽象數據類型(ADT)。這是個好主意,擴展RDBMS的能力。開發商爲這個技術使用了許多名字,例如Oracle cartridge和Informix data blades。ADT的缺點是它們把你緊緊綁在特定的一個開發商上;ADT的範疇超越了SQL標准。因此,你應該只在ADT的好處很明顯的時候才使用。 在關于ADT如何適合數據庫開發的著作裏有一些混亂。假如你使用OMT開發過程,你能夠用屬性實現簡單域,用ADT實現複雜域。你仍應該用表實現類。 SQL3指針。最新的SQL標准的版本,SQL3,加入了作爲一種數據類型的指針符號。顯然,其意圖是支持導航和面向對象。我們對于SQL3指針最友善的評語是,它們是嫁接的,是可以忽略的。更深入的批評是,指針在理論上是荒謬的,增加了複雜性,又沒有擴展SQL的表達能力。CJ Date在上次的九月對象/關系型會議上雄辯地討論了這一點[iv]。 好了,那麽我們冷淡地對待抽象數據類型和SQL指針的指責。但我們相當喜歡面向對象技術和關系型數據庫。有兩個爲RDBMS的擴展可以使它們更輕易用于OO技術。我們將很樂意看到RDBMS開發商把這些能力加入到他們的産品中。 擴展的參考完整性動作來支持泛化。當前的參考完整性機制是單向的。爲了完全支持泛化,我們需要一個雙向的機制。這樣,一條超類記錄就可以依靠一條子類記錄。並且,一條子類記錄就可以依靠一條超類記錄。我們通過例子可以最好地解釋這點。 圖15摘錄于我們的在參考文獻3的財務案例學習。我們用資産超類來統一某些沒有顯示在摘錄裏的通用的數據和功能。一項資産可以是一支股票或股票期權。一支股票可以有許多它的股票期權。例如,IBM股票可以有許多寫明達到價格和過期日期的期權。 [url=/bbs/detail_1785878.html][img]http://image.wangchao.net.cn/it/1323421609223.gif[/img][/url]> 圖15 參考完整性和泛化的例子。 我們推薦的泛化實現是單獨的表 - 映射該超類和每個子類爲一個表。然後,我們就可以使用參考完整性使股票期權和股票的記錄依靠于資産。一個資産記錄的刪除級聯到相應的子類記錄、股票期權或股票的刪除上。我們也能夠定義一個參考完整性動作,這樣一個股票的刪除就級聯到關聯的股票期權記錄的刪除。 現在問題如下:假如我們刪除的一項資産是一支股票,資産記錄的刪除級聯到引起股票記錄的刪除。隨後,股票記錄的刪除級聯引起所有股票期權記錄的刪除。但現在參考完整性使我們失敗了:一條股票期權記錄的刪除並不引起一項資産記錄的刪除。刪除級聯只能從超類走到子類。爲了完全的行爲,級聯應該雙向地走下去。 當前有用的參考完整性的工作是做更多的編程(也即做更多的工作和承擔更多的故障風險)。在我們的案例學習的實現裏,用戶隨時要刪除一項是股票的資産,我們不得不書寫額外的代碼來首先檢查關聯股票期權的存在性,然後刪除它們。 支持交叉表的記錄劃分。單繼續(泛化的最常見方式)的含義是一個超類的每個實例都是用最多一個子類來例示。現在的RDBMS不能輕易地加強這個約束。例如,沒有什麽防止下面的情形。一支股票可以用ID18加入到資産表,用ID18加入到股票表,並且也可以用ID18加入到股票期權表。再一次地,我們爲了確信行爲的完整,不得不作額外的編程,而不是寫一個簡單的聲明約束。 5. 結論 本文陳述了用關系型數據庫實現UML模型的快速的概觀。我們希望本文向你演示的技術是十分適用的。一個練習有素的開發人員能夠用關系型數據庫預備一套優秀的OO模型的實現。假如你要關于實現機制的更多的細節,參考3有另外的信息,並且也覆蓋了我們沒有在這裏討論的一些高級模型建模結構。 關于作者 Michael Blana是紐約Schenectady的通用電氣研發部的畢業生(譯者按:這是作者幽默的說法,意思是他已經跳槽了)。在過去的五年裏,他已經成爲面向對象技術、建模、數據庫設計和逆向工程領域的獨立的産業顧問。Blaha博士是多篇論文、五個專利和兩本書的作者。可以通過www.omtassociates.com或blaha@acm.org和他聯系。 William Premerlani從1975年開始就在通用電氣研發部供職。他的主要研究愛好在軟件工程、元建模(metamodeling)、數據庫技術和複雜工程應用等領域。Premerlani博士是許多論文、二十五個專利和兩本書的作者。通過premerlani@acm.org和他聯系。 參考資料 [i]Michael Blaha and William Premerlani. Object-Oriented Design of Database applications. Rose Architect 1,2 (Winter, 1999). [ii] PPS Chen. The Entity-Relationship model - toward a unified view of data. ACM Transactions on Database Systems1, 1 (March 1976). [iii] Michael Blaha and William Premerlani. Object-Oriented Modeling and Design for Database Applications, Prentice Hall, Englewood Cliffs, New Jersey, 1998. [iv] CJ Date. Don't mix pointers and relations! Presentation at Third Annual Object/Relational Summit sponsored by Miller Freeman, Washington D.C., September 16-19, 1998. (責任編輯:銘銘)
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 熱帖排行
 
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有