pureXML 概述
pureXML 是 DB2 V9 引入的極其重要的新特性,使得 DB2 DBMS 對於 XML 數據的存儲和管理煥然一新。在 pureXML 之前,DB2 管理 XML 的常用方法有兩種:
將 XML 作為一個整體保存在大對象(CLOB/BLOB)中;
將 XML 分解映射到關系表中。
前者不能很好的支持查詢 XML 片段或特定的元素 / 屬性 / 子樹;後者使得 XML 數據的處理變得非常復雜,而且在某些情況下會產生 XML 數據的失真。pureXML 則原生態的保存了 XML 固有的層次結構,在提高 XML 數據訪問細粒度的同時,消除了 XML 數據關系化的計算的復雜度和不必要的性能開銷。
此外,pureXML 支持對 XML 特定的元素 / 屬性建立索引,能夠快速的搜索 XML 子樹;完全基於行業標准的新的查詢語言支持(XQuery 和 SQL/XML)和新的查詢優化技術;支持對 XML schema 的管理、驗證和演進;提供良好的 API 和數據庫管理工具。很多讀者對於 DB2 pureXML 技術比較熟悉,本文不再贅述。
組件庫技術簡介
隨著信息技術的迅速發展,計算機軟件系統在各個行業中的應用越來越廣。在軟件產品的開發過程中,有效地復用已有的軟件組成單元,可以避免同質軟件部分的重復設計、開發、測試和文檔化,對於減低開發成本、縮短開發周期以及提高產品質量都有非常重要的意義,因此基於組件的開發方法被引入了軟件工程。
基於組件的軟件開發主要包括組件開發和組件組裝兩個方面的內容。
組件開發,就是遵從一定的規范要求和接口參數,編寫具有特定功能的軟件系統的結構部件;
組件裝配,就是將待構建軟件系統分解成較低級別的功能模塊,選擇適當的已有組件進行組合裝配。
由此可見,在基於組件的軟件開發中,具有高效的存儲、組織、管理和檢索功能的通用組件庫至關重要。組件庫可以有效的組織和存儲已經開發的組件信息,新的組件可以加入到組件庫中,不再需要的組件可以從組件庫中刪除;組件庫可以提供高效的組件檢索功能,在構建軟件系統時需要的組件可以快捷的從組件庫中查詢得到。
那麼,如何構建一個高效的通用組件庫呢?這就涉及到兩個基本的問題:1)組件的描述,即采用什麼樣的方法來刻畫和表達通用的組件;2)組件的檢索,即如何能快速准確的查詢到所需要的目標組件。
1. 組件的描述模型
由於組件本身所具有的復雜性以及確定分類結構的困難,在軟件工程領域,提出了很多方法來表達和刻畫組件,對組件進行分類和組織。有一些描述方法比較直觀,比如關鍵詞描述;有一些描述方法顯得比較復雜一些,比如超文本鏈接法和人工智能法等。其中全方位、多角度刻畫組件的描述方法被廣泛使用,這一典型的方法被稱為面向刻面(Facet OrIEnted)技術。
所謂刻面描述是將術語置於一定的語境中,並通過特定的反映組件本質特性的視角(刻面)進行精確的描述,刻面可以理解為某個領域的基本描述特征。一個組件可以用多個刻面來表達,每個刻面中可以有多個術語來刻畫,不同的刻面從不同的角度來描述組件的本質性特征。每個刻面具有一組可選的術語,術語僅限於在給定的刻面之中取值(受控詞匯表)。這樣,對於組件的描述存在一個術語空間,在組件和這一術語空間形成一種映射。
通俗的講,面向刻面的組件描述方法,就是從多個角度進行刻畫描述,比如組件的功能、組件開發所用的語言、組件適用的 OS 平台等。容易看出,面向刻面的組件描述模型,本質上,就是為組件建立一種描述樹,下圖給出了一個描述樹的示例。
圖 1. 面向刻面的組件描述樹
查看原圖(大圖)
圖 1 是一種典型的組件描述的刻面樹,對組件的描述由刻面和術語兩大部分組成。其中方框代表刻面,橢圓代表術語。刻面由一組描述組件本質特征的視角組成,每個刻面從不同的側面對組件庫中的構件進行分類,一個組件首先可以從“組件功能”和“應用環境”兩個刻面進行描述。刻面遵照父子關系構成一棵刻面樹,兄弟刻面之間是正交關系,分別表示了對於父刻面來說不同的描述角度,同時又是互補關系,綜合起來才能使父刻面獲得較為完整的描述,組件的“應用環境”是由“軟件環境”和“硬件環境”兩個正交又互補的關系組成的。每個刻面又由一組術語構成,稱為術語空間。同一刻面下的多個術語之間按照繼承關系同樣構成一個樹形結構,子術語與父術語是特殊和一般關系, “Windows”操作系統與“Win 9x”、“Win NT”、“Win CE”之間即為特殊與一般的關系。
一般地說,面向刻面的通用組件可以通過以下這些刻面進行描述。
功能(function):組件對外提供的服務或完成的任務,一般地,它是組件輸出和輸入之間的映射;
接口(interface):組件的輸入 / 輸出參數的個數和類型,組件之間信息傳輸遵循的協議;
實現(implement):組件被實現時采用的語言及版本、組件存在的具體形態(如文件類型 .class 或 .dll 等);
環境(environment):組件正確有效運行的基礎設施要求,包括操作系統、數據庫、網絡、編譯系統等;
領域(domain):組件適用的領域,領域分類標准可參考國民經濟行業代碼 (GB/T 4754 — 2002),包括農業、采礦業、制造業、建築業、交通運輸、金融業、地產業、教育和醫藥衛生等;
其它(other):不宜歸類到上述六個維度的其它描述組件的信息。
描述組件的刻面具有很強的伸縮性,支持描述的進一步細分,支持描述的聚合,可以適度裁剪,既滿足面向不同應用類型和應用領域的軟件組件庫的特殊要求,又能滿足組件庫本身更新升級的需要。
2. 組件的檢索
組件的檢索方法依賴於組件的描述模型,面向刻面的組件檢索就是檢索條件樹與目標組件描述樹的匹配過程。
首先,將用戶的檢索條件轉化為一棵檢索條件刻面樹;然後,將此檢索條件樹與組件庫中所有組件的刻面描述樹進行匹配,如果找到一種允許的映射方案,那麼該組件即為滿足檢索條件的一個檢索結果;最後,對於不能完全匹配的組件,可以通過對匹配度阈值的設定,選出滿足給定匹配度的檢索結果,實現條件松弛的組件檢索。
使用 pureXML 技術
通過前面章節的介紹,我們容易發現,pureXML 技術非常適合用來實現面向刻面的組件庫。面向刻面的組件數據模型天然的可以使用 XML 來予以描述。而組件的檢索也就是使用 SQL/XML 或 XQuery 查詢滿足條件的 XML 文檔或想要獲取的 XML 節點或子樹,檢索條件可以用一個或多個 Xpath 的組合表達,不同松弛程度的匹配可以通過 Xpath 指定的檢索條件的強度實現。通用組件庫管理軟件的開發者不再需要將為組件信息建立一個由多個關系表構成的數據描述模型,在組件描述信息的 XML 結構變更時,重新進行從 XML 到關系表的映射。
下面我們通過一個簡單的例子,詳細介紹如何 pureXML 構建一個基本的面向刻面的組件庫。
1. 組件描述的 XML 模型
我們要構建的組件庫是基於 J2EE 平台的業務組件庫,可以為各個領域的企業構建企業管理軟件。所有組件分為兩類:原子邏輯和組合邏輯。
原子邏輯,顧名思義,就是完成最基本的業務操作;
組合邏輯,將原子邏輯組合起來,完成各種復雜的業務。
每一個組件都有一個短語描述其功能,從業務邏輯的角度又可以進一步劃分為認證、工作流、數據庫操作、數據對象操作、文件操作、打印、調試和通用等多種操作編目;組件的接口描述中包括輸入和輸出的參數個數和類型,不涉及到接口之間的協議;組件可以跨操作系統,數據庫和網絡組件運行的環境,也都被基礎平台所屏蔽。所以,描述該組件庫組件的刻面包括:功能(function)、接口(interface)、實現(implement)及編目(catalog)。這樣,平台業務組件的精確描述模型可用下面的 XML 示意。
清單 1. 組件的 XML 描述
<?XML version="1.0" encoding="UTF-8"?>
<component compID="101" reference="separate"
entity="com.xicrm.business.XiJoinInStringListSeparator">
<function>concate two strings with given separator</function>
<interface>
<input type="Java.lang.String" meaning="string #1"/>
<input type="Java.lang.String" meaning="string #2"/>
<input type="Java.lang.String" meaning="separator"/>
<output type="Java.lang.String" meaning="string concated"/>
</interface>
<implement type="atomicLogic"/>
<catalog name="generic">
<detail>string Operater</detail>
</catalog>
</component>
除了組件的功能、接口、實現和編目信息,本例 XML 描述中還包含組件的編碼(compID)、引用(reference)及實體名稱(entity),其具體含義如下。
組件編碼,是每一個組件的身份識別,即唯一編號,可能由數字或字母等字符構成;
引用,是調用組件的直接操作名稱,即 Java 類的方法名;
實體名稱,組件對應的 Java 類的全局指示符,即完整的類名。在基於組件的軟件開發框架或工具中,通過 Java 的反射機制創建該類的實例。
2. 組件的 XML Schema
如同傳統的關系型數據可以通過約束(constraint)保證數據的有效性和完整性一樣,XML 數據也可以通過一定的技術方法保證其有效性和完整性,這種方法就是通過 XML Schema 來實現的。XML Schema 定義了 XML 文檔的組成元素 / 屬性的名稱、類型、在文檔中出現的次數、順序,進而定義了這些要素構成的 XML 文檔結構。
對於清單 1 的 XML 描述,可以使用如下 XML Schema 予以約束。
清單 2. 組件的 XML Schema
<?XML version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
XMLns:cs="http://www.w3.org/2009/09/componentBase"
targetNamespace="http://www.w3.org/2009/09/componentBase"
elementFormDefault="qualifIEd">
<xs:element name="input" type="cs:InputType"/>
<xs:complexType name="InputType">
<xs:attribute name="type" type="xs:string" use="required"/>
<xs:attribute name="meaning" type="xs:string" use="required"/>
</xs:complexType>
<xs:element name="output" type="cs:OutputType"/>
<xs:complexType name="OutputType">
<xs:attribute name="type" type="xs:string" use="required"/>
<xs:attribute name="meaning" type="xs:string" use="required"/>
</xs:complexType>
<xs:element name="interface" type="cs:InterfaceType"/>
<xs:complexType name="InterfaceType">
<xs:sequence>
<xs:element ref="cs:input" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="cs:output" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:element name="implement" type="cs:ImplementType"/>
<xs:complexType name="ImplementType">
<xs:attribute name="type" type="xs:string" use="required"/>
</xs:complexType>
<xs:element name="catalog" type="cs:CatalogType"/>
<xs:complexType name="CatalogType">
<xs:sequence>
<xs:element name="detail" type="xs:string"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
<xs:element name="component" type="cs:ComponentType"/>
<xs:complexType name="ComponentType">
<xs:sequence>
<xs:element name="function" type="xs:string"/>
<xs:element ref="cs:interface"/>
<xs:element ref="cs:implement"/>
<xs:element ref="cs:catalog"/>
</xs:sequence>
<xs:attribute name="compID" type="xs:string" use="required"/>
<xs:attribute name="reference" type="xs:string" use="required"/>
<xs:attribute name="entity" type="xs:string" use="required"/>
</xs:complexType>
</xs:schema>
為了使用上述 XML schema 驗證組件的 XML 描述信息,清單 1 給出的 XML 需要添加對 XML Schema 定義的目標命名空間(namespace)的引用,即在 XML 的根節點 component處添加默認的命名空間。
清單 3. 組件的 XML 命名空間
XMLns="http://www.w3.org/2009/09/componentBase"
指定了缺省命名空間的完整 XML 信息如下。
清單 4. 組件帶命名空間的 XML 描述
<?XML version="1.0" encoding="UTF-8"?>
<component XMLns="http://www.w3.org/2009/09/componentBase"
compID="101" reference="separate"
entity="com.xicrm.business.XiJoinInStringListSeparator">
<function>concate two strings with given separator</function>
<interface>
<input type="Java.lang.String" meaning="string #1"/>
<input type="Java.lang.String" meaning="string #2"/>
<input type="Java.lang.String" meaning="separator"/>
<output type="Java.lang.String" meaning="string concated"/>
</interface>
<implement type="atomicLogic"/>
<catalog name="generic">
<detail>string Operater</detail>
</catalog>
</component>
這樣與此結構一致的 XML 信息才能夠被存儲到組件庫中,也就完全保證了描述組件的 XML 數據的合法性。
3. 創建數據庫對象
本文所有命令腳本和實驗操作均基於 DB2 v9.7,讀者可以從 http://www.ibm.com/db2/express下載免費版本。
通過下面的命令,創建通用組件庫 CompBase 以及最基本的數據表 component。表 component 有兩個最基本的組件序號 id 和組件的 XML 描述信息 info,此處組件序號 id 可以為獲取組件庫的統計信息提供方便,與 XML 信息中的組件編碼含義不盡相同。
清單 5. 組件庫的建立
db2start
SQL1063N DB2START processing was successful.
db2 create db CompBase using codeset utf-8 territory CN
DB20000I The CREATE DATABASE command completed successfully.
db2 connect to CompBase
Database Connection Information
Database server = DB2/LinuxX8664 9.7.1
SQL authorization ID = CSLIU
Local database alias = COMPBASE
db2 "create table component (id int, info XML)"
DB20000I The SQL command completed successfully.
4. 組件入庫
創建了數據庫以及基本的數據表之後,我們就可以將已有的組件信息存儲到數據庫之中了。組件信息入庫可以通過單個入庫和批量入庫進行,DB2 v9.7 完全支持這兩種方式。
單個組件入庫,可以通過組件庫軟件系統前端程序方便的錄入生成符合清單 2 所示 XML Schema 要求的 XML 信息,再執行 SQL 語句完成。其實質就是 XML 數據的帶驗證的插入操作,也就是說在將 XML 數據插入數據庫之前首先對其是否滿足 XML Schema 進行驗證,這樣就保證了進入組件庫的描述信息是有效的、完整的。
所以在進行真正組件入庫操作之前,需要將 XML Schema 注冊到數據庫中,供驗證組件的 XML 描述信息使用。
清單 6. 注冊 XML Schema
db2 "register XMLschema 'http://www.w3.org/2009/09/componentBase'
from component.xsd as compSchema"
DB20000I The REGISTER XMLSCHEMA command completed successfully.
db2 complete XMLschema compSchema
DB20000I The COMPLETE XMLSCHEMA command completed successfully.
其中, component.xsd就是清單 2所示的 XML Schema的定義文件。
然後,執行下面的腳本,將清單 4 所示的組件信息驗證後保存到數據庫中。
清單 7. 插入 XML 數據
insert into component(id, info) values(1, XMLVALIDATE(XMLPARSE(DOCUMENT
'<?XML version="1.0" encoding="UTF-8"?>
<component XMLns="http://www.w3.org/2009/09/componentBase"
compID="101" reference="separate"
entity="com.xicrm.business.XiJoinInStringListSeparator">
<function>concate two strings with given separator</function>
<interface>
<input type="Java.lang.String" meaning="string #1"/>
<input type="Java.lang.String" meaning="string #2"/>
<input type="Java.lang.String" meaning="separator"/>
<output type="Java.lang.String" meaning="string concated"/>
</interface>
<implement type="atomicLogic"/>
<catalog name="generic">
<detail>string Operater</detail>
</catalog>
</component>' PRESERVE WHITESPACE) ACCORDING TO XMLSCHEMA ID compSchema))@
一般來說,通用組件庫的系統程序會與數據庫建立連接並完成插入 XML 數據的操作。批量組件入庫,則可以通過使用 DB2 實用工具 Load 或 Import 來完成,本文由於篇幅原因不再贅述。
5. 組件出庫
組件入庫以後,在構建一個完整的軟件系統時,我們可以根據特定的查詢條件,比如組件的功能、編目類別和接口參數等,從組件庫中查找到所需組件進行組裝。
查詢 XML 信息可以使用 DB2 v9 完全支持的 SQL/XML 或 Xquery 語句,獲取滿足條件的組件信息。在本例中,組件的 entity 和 reference 是組裝組件必需的信息,基於組件的軟件開發框架或工具中,通過 Java 的反射機制創建該組件所屬對象的實例,並調用組件方法 ( 當然,組件庫中的所有組件編譯後的 Java 庫文件,必須在軟件編譯及運行時能夠訪問 ),完成軟件的部分功能。
例如,我們可以使用 SQL/XML 查找功能為“用給定的分隔符連結兩個字符串(concate two strings with given separator)”的組件,腳本如下。
清單 8. 使用 SQL/XML 查詢組件信息
SELECT temp.entity, temp.reference
FROM component C,
XMLTABLE('declare namespace cs="http://www.w3.org/2009/09/componentBase";
$info/component' PASSING C.info AS "info"
columns entity
varchar(200) path './@entity',
reference varchar(200) path './@reference'
) as temp
WHERE XMLEXISTS('$info/*:component[*:function="concate two strings
with given separator"]' PASSING C.info AS "info")@
我們也使用 Xquery 返回需要的組件信息,如果需要 XML 描述信息中的多個節點,可以在返回語句中構造基於組件的軟件開發框架或工具方便處理的結構。