概述
從80年代中期開始,随着C++語言的成功,面向對象語言已經成為軟體開發中的主導語言。現在很多商用軟體,尤其是企業資訊系統,都是使用面向對象語言進行開發的。應用面向對象方法,我們通過類來抽象不同類别的實體,屬性來表示實體的靜态特征,關聯來抽象實體間的聯系,繼承來抽象類别的包含關系。
很多的應用程式都需要進行資料存儲,關系型資料庫是最常用的資料管理系統。在關系型資料庫中,表、列和外鍵是抽象資料的基本元素。關系型資料庫是建立在關系計算和布爾代數基礎之上的,SQL是資料庫的操作語言,通過關系運算,連接配接、聯合等,來操作資料。
我們很容易的看出,面向對象模型和關系模型是不完全比對的。比如
1. 對象可以存儲到多張表,表也可以存儲多個類的對象。
2. 對象之間的關系是雙向的,而表之間的關系是單向的。
3. 對象之間有繼承關系,表之間沒有。
為了解決這種不比對,人們定義了很多映射模式來建立兩種模型間的對應關系。這些映射模式邏輯上解決了模型間的不比對,使得面向對象程式能夠正确地和關系關系型資料庫進行互動,但是對于程式的開發,仍然有很多問題需要解決。
問題
對于設計人員來說,他們需要找到并且描述這兩種模型元素間的映射關系,以便程式設計人員能夠正确地實作資料的存儲和查詢。現在很多模組化工具僅提供其中一種模型的支援,比如Together僅支援對象模組化,ERWin僅支援資料模組化。即使同時支援兩種模型,這種支援也很不完整,比如Rose中的資料模組化功能。分析設計人員常常需要兩種不同的工具來進行模組化,如果他們想描述這兩種模型元素間的對應關系,他們隻能通過文檔或者表格的形式。這很容易産生錯誤,并且如果模型發生改變,這些文檔需要手工更改,容易造成不一緻,維護起來很困難。
對于編碼人員,他們需要應用某種技術來實作模型的這種對應關系。如果通過語言提供的資料庫通路接口,比如Java的JDBC或者.Net的ADO.Net,對于每一個對象的每一個存儲操作,編碼人員需要編寫存取操作的SQL,資料庫控制和通路代碼,這是一項繁瑣、重複性的勞動。即使應用O/R 映射的架構,比如Hibernate, EJB 3.0或者.Net平台的NHibernate,他們需要編寫映射檔案或者通過标記來定義O/R映射架構所需要的映射中繼資料。這些映射中繼資料隻不過是我們在設計階段定義的映射關系另外一種表現方式,轉換成XML或者标記的方式,無疑這種轉換增加了錯誤的可能性和維護的難度。
PowerDesigner解決之道
PowerDesigner提供對于多達8種模型的支援,其中包括面向對象模型和關系資料模型。作為一個內建的企業模組化工具,PowerDesigner并不是簡單的将幾種模型工具羅列在一起。各種模型互相之間可以建立關聯,通過這種關聯,它提供了企業模型統一、一緻的視圖。其中模型間的映射和自動生成是建立模型間關聯重要的手段。
模型可以描述系統的靜态特征和動态特征,而靜态特征可以用來表述系統的持久狀态,比如面向對象模型中的實體類,資料庫模型的表,XML模型中的元素節點等。在PowerDesigner中,我們可以在各種可以描述持久狀态模型間建立映射,比如XML模型到面向對象模型間的映射,面向對象模型到關系資料模型的映射等。下面我們就來看一下,PowerDesigner是如何支援面向對象模型到關系模型的映射的。
1.1 對象/關系映射
下表列出了PowerDesigner中面向對象元素和關系模型元素間的對應關系:
OOM 元素 | PDM 元素 |
域 | 域 |
類 | 表 |
接口 | 無 |
屬性 | 列 |
辨別符 | 鍵 |
操作 (具有存儲過程範型) | 存儲過程 |
操作 (具有存儲功能範型) | 存儲功能 |
關聯 | 外鍵或者表 |
關聯類 | 表和兩個指向關聯的類所生成表的外鍵 |
繼承 | 表或者外鍵 |
依賴 | 無 |
實作 | 無 |
引用 | 無 |
在PowerDesigner中,我們可以通過三種方式來建立面向對象模型和關系模型間的映射:
1. 手工建立映射。
2. 自動模型生成。
它們分别适用于不同的開發需求,下面我們就來看如何通過這兩種方式來建立映射。
1.2 手工建立映射
這種方式适用于以下幾種情況:
1. 在已經存在的模型間建立映射。企業的資訊系統是一個異構的環境,很多應用程式和資料庫都是獨立開發的,它們具有不同的模型,如果它們之間需要進行資料互動,則需要建立它們之間的映射,比如新的ERP系統中和企業原有的資料庫間的映射。
2. 資料庫和程式由不同的組負責設計。大型的企業應用程式可能包含很多業務子系統,每個業務子系統隻考慮如何實作它自己的業務需求,而資料庫設計要從整體出發,考慮整個應用程式的需求。對于每個業務子產品,需要定義它的邏輯模型和資料庫模型間的映射。
在建立映射之前,我們需要給面向對象模型建立資料源,然後添加要映射的資料庫模型。表1中可以映射的面向對象元素都有一個映射的定義視窗,比如下圖所示的類的映射屬性頁。通過這個映射屬性頁,使用者可以添加或者删除對應的資料庫模型元素,這些元素隻能是表1中該元素對應的類型。

像其他模型的中繼資料一樣,PowerDesigner會把映射中繼資料存儲在模型中,映射中繼資料通過快捷方式來記錄對應的模型元素。如果對應的模型發生改變,比如表的名稱發生改變,對于映射中繼資料沒有影響。當使用者需要得到對應中繼資料的屬性的時候,PowerDesigner會解析快捷方式,找到目标元素,使用者得到的是目前元素的資訊,對比于文檔或者表格,這種方式提高了一緻性和可維護性。而且PowerDesigner提供了變更影響分析視圖,它可以幫助使用者在變更之前分析可能産生的影響,比如在改變列的類型之前,使用者可以了解到是否會造成映射到此列的屬性類型的不比對。
也許使用者認為這種操作方式太複雜,使用者需要切換到每個面向對象的視窗來定義它的映射。從PowerDesigner 12開始,使用者可以通過另外一種更加便捷的方式,映射編輯器,來定義元素間的映射關系。映射編輯器提供了一種All-In-One的操作方式,通過元模型和目标模型的樹狀視圖,使用者可以友善的通過托拽的方式來定義所有的映射。
1.3 模型自動生成
在很多時候我們要開發一個全新的系統,而資料庫僅僅考慮這個系統的資料管理需求,或者開發新的應用程式通路已有的資料庫。采用面向對象方法的軟體開發通常采用自頂向下的開發過程,先建立企業的應用模型,然後再進行資料庫設計。使用者也可以采用自底向上的開發過程,也就是以資料為中心的開發過程,先進行資料庫設計, 或者應用已有的資料庫模型,再設計應用程式模型。
既然我們定義了模型間映射模式,如果有了一種模型,為什麼不能自動生成另外一模型,并且建立它們間的映射。PowerDesigner就提供了這種模型的自動生成功能,使得使用者能夠重用現有的模型,友善的生成目标模型。對于面向對象模型和資料庫模型來說,這種自動生成功能是雙向的,即可以通過面向對象模型來生成資料庫模型,也可以通過資料庫模型來生成面向對象模型。
1.3.1 自動生成資料庫模型
這種模式适合于自頂向下的開發過程,即先建立應用程式模型,再設計資料庫。我們可以應用PowerDesigner提供的轉換模式,将應用程式模型中描述持久資訊的面向對象元素,實體類、關聯、繼承,生成資料庫模型對應的元素。
根據已經被證明的映射模式,PowerDesigner提供了一些預設的轉換模式,使用者也可以定制轉換模式來控制生成過程
1.3.1.1 基本轉換模式
1. 類
使用者可以通過類的持久屬性和生成類型來控制類的自動轉換,PowerDesigner僅會自動轉換持久的類。轉換的類型有表、遷移列和抽象資料類型,其中表和抽象資料類型都容易了解,遷移列主要控制繼承中類的轉換,我們會在繼承轉換中詳細讨論它的用法。使用者還可以指定生成表的名稱。
2. 屬性
如果持久類的生成類型不是抽象資料類型,PowerDesigner會将該類中的持久屬性轉換成表的列。PowerDesigner提供了一些預設的轉換模式,比如資料類型的對應關系。使用者可以定制轉換的過程,他可以定義生成列的一些屬性,名稱、類型、長度等。
3. 辨別符
持久類的辨別符會被轉換成表的鍵,主辨別符會被轉換成主鍵。
4. 操作
如果持久類的操作具有存儲過程或者存儲函數的範型,相應的存儲過程或者存儲函數會被生成。
1.3.1.2 關聯轉換
PowerDesigner會根據關聯生成外鍵和表,支援所有的關聯映射模式。
關聯 | 轉換規則 |
一對一 | 對于單向的關聯,一個外鍵會生成,外鍵的方向和關聯的方向一緻,父表的主鍵會遷移到子表中作為外鍵。對于雙向的關聯,兩個外鍵會被生成,使用者需要手動删除其中的一個 |
一對多 | 不管單項還是雙向,隻有一個外鍵被生成,多端持久類生成的表為子表,父表的主鍵會遷移到子表中作為外鍵 |
一對多遷移主鍵 | 這是一對多關聯的變體,如果一對多關聯具有組合并且由一端包含多端,那麼被遷移到子表的列同時又會是主鍵的一部分 |
多對多 | 會生成一個中間關聯表和兩個外鍵,其中兩端持久類的表的主鍵會遷移到關聯表中作為主鍵和外鍵,兩個外鍵由中間關聯表分别指向它們 |
使用者可以通過端點的度來控制外鍵是否為必需的,如果子表對應的持久類端的最小度為1,那麼外鍵為必需的,即子表的外鍵列是非空的;如果為0,那麼外鍵為可選的。
1.3.1.3 繼承轉換
PowerDesigner會将繼承轉換成表和關聯,使用者通過基本映射中提到的生成類型來控制轉換,生成類型表表示對于該持久類單獨的表會生成,生成類型遷移清單示該類屬性生成的列會存在于其他類生成的表中,沒有單獨的表會被生成。
映射模式 | 說明 | 設定 |
繼承層次到單表映射 | 整個繼承層次會被轉換成一張表,通過表中的分類列來區分不同的類 | 根類生成類型為表,其他所有子類的生成類型為遷移列,根類需要設定主辨別符 |
每類一表映射 | 對于繼承層次中的每一個類,單獨的表會被生成,子類的表和父類的表通過外鍵關聯,外鍵的列同時作為子類表的主鍵 | 所有類的生成類型為表,根類需要設定主辨別符 |
每具體類一表映射 | 隻有繼承層次中的葉子節點類會被轉換成表,每一個非葉子節點類屬性生成的列會被遷移到葉子類的表 | 所有非葉子節點子類的生成類型為遷移列,葉子節點的生成類型為表,根類需要設定主辨別符 |
PowerDesigner也支援混合映射模式的轉換,不過這種轉換并不常用,使用者可以參考PowerDesigner的文檔檢視詳細用法。
1.3.1.4 其他映射模式的支援
PowerDesigner還可以通過嵌入來支援細粒度的轉換。比如,在員工資訊類中,我們有一個屬性家庭住址,該屬性是對象類型,類型為位址類。我們不想為位址類單獨生成表,隻想把它嵌入到員工資訊表中。在PowerDesigner中,我們可以通過,設定屬性的類生成類型為嵌入來實作這一點。
1.3.2 自動生成面向對象模型
PDM到OOM的轉換适合于自底向上的開發過程,對于以資料為中心的應用系統或者通路已有資料庫上的應用系統,這種轉換是非常有用的。PDM到OOM的轉換類似于OOM到PDM轉換的逆過程,PowerDesigner會把PDM中的元素轉換成OOM中對應的元素。但是其中繼承的轉換是不可逆的,因為PDM中沒有子類的概念,是以使用者需要手工更改生成後的對象模型。
1.3.3 模型和并
PowerDesigner提供了模型合并功能,支援疊代式的模型自動轉換。自動生成的目标模型并不一定完全滿足我們的需要,我們常常要對它進行修改,但是源模型也發生了改變,有時我們既想同步目标模型和源模型,又想保持我們對目标模型所作的修改,這時模型的合并顯得非常重要。通過PowerDesigner的模型合并視窗,使用者可以了解到重新生成的模型和目前的目标模型的差異,進而可以根據自己的需要,選擇是否保持或者覆寫以前的模型。
使用者還可以通過PowerDesigner的流體模型了解源模型和目标模型間的轉換關系。
1.4 自動代碼生成
從上面可以看到,通過PowerDesigner,設計人員可以友善的完成應用程式的設計、資料庫設計以及O/R映射定義,那麼程式設計人員通過編碼實作這些設計。對于O/R映射的實作,我們可以看到,不管使用什麼技術,編碼人員都需要進行大量的工作。
我們知道MDA的目标就是把現有的以代碼為中心的開發模式轉換成以模型為中心的開發模式,讓模型生成代碼,把開發人員從繁瑣的編碼工作中解放出來,進而專注于系統的架構和業務邏輯上。PowerDesigner通過其可擴充性提供了對于MDA的支援。在PowerDesigner中,所有的模型都是通過元模型進行描述的,可以通過GTL(通用模闆語言)和VBScript來通路這些元模型。那麼我們可以通過元模型的資訊來做他想要做的事,包括自動代碼生成。
PowerDesigner已經提供了對于主要持久化技術的支援,Hibernate、EJB 3、NHibernate、ADO.Net等,使用者可以直接使用這些擴充模型。除了O/R映射實作代碼,這些擴充模型還可以生成測試代碼,友善使用者對生成的代碼進行測試。使用者隻需要添加相應的擴充模型,并且通過擴充屬性設定特定擴充模型所需的資訊,就可以實作自動代碼生成。下圖是應用Hibernate擴充模型生成映射檔案的預覽視窗。
使用者也可以對這些擴充模型進行定制或者開發他自己的擴充模型,以滿足自己的需要。關于如何擴充PowerDesigner,可以參閱PowerDesigner使用者文檔和進階使用手冊。
結論