即使數據庫沒有自稱支持 XML 特性,也可以在關系數據庫中存儲和檢索 XML 文檔。這樣做需要小心地使用Java™ 編程語言(數據庫不一定兼容 Java Database Connectivity 或 JDBC),還需要一個框架來連接關系數據庫和 XML 文檔流。
將 XML 映射到數據庫有兩種常見的方法:基於表的映射和對象-關系(或基於對象的)映射。這兩種方法都是雙向的,因此可用於存儲和檢索 XML 文檔。
基於表的映射
基於表的映射 將文檔看作一個表或者一組表。清單 1 和 2 顯示了這兩種情況下的文檔結構。
清單 1. 表映射的選項(單表)
<Table ABC>
<Row1>
<Column_a>123-45-7890</Column_a>
<Column_b>Johnson, Eric</Column_b>
<Column_c> PharMaceutical </Column_c>
</Row1>
<Row2>
<Column_a>999-00-1010</Column_a>
<Column_b>Mitchell, Bruce</Column_b>
<Column_c> Industrial </Column_c>
</Row2>
</Table ABC>
清單 2. 表映射的選項(多表)
<Tables>
<Table_1>
<Row1>
<Column_a>123-45-7890</Column_a>
<Column_b> Johnson, Eric </Column_b>
<Column_c>Company A</Column_c>
</Row1>
<Row2>
<Column_a>999-00-1010</Column_a>
<Column_b> Mitchell, Bruce </Column_b>
<Column_c> Company B</Column_c>
</Row2>
</Table_1>
<Table_2>
<Row1>
<Column_a>Company A</Column_a>
<Column_b>PharMaceutical</Column_b>
</Row1>
<Row2>
<Column_a>Company B</Column_a>
<Column_b>Industrial</Column_b>
</Row2>
</Table_2>
</Tables>
這種映射最明顯的優點是簡單。因為結構與關系數據庫的表及結果集匹配,根據這種映射編寫代碼很容易。代碼執行快、伸縮性好,對某些應用很合適,比如每次一個表在數據庫之間傳遞數據。
但是,基於表的映射也有一些不足之處。它只能用於非常小的 XML 文檔子集。此外,它沒有保留物理結構(即字符和實體引用、字符編碼或獨立的聲明)、文檔信息(即文檔類型聲明或 DTD)、注釋和處理指令。
對象-關系映射
基於表的映射只能用於有限的 XML 文檔,因此多數支持 XML 的關系數據庫、大部分支持 XML 的對象服務器以及一些中間件工具使用更加復雜的映射,稱為對象-關系映射。這種映射方法將 XML 文檔建模為針對文檔數據的一棵對象樹,然後將這些對象映射到數據庫。
比如 清單 3 所示的 XML 文檔。
清單 3. XML 格式的單個銷售訂單 <SalesOrder>
<Number>1234</Number>
<Customer>Gallagher IndustrIEs</Customer>
<Date>29.10.00</Date>
<Item Number="1">
<Part>A-10</Part>
<Quantity>12</Quantity>
<Price>10.95</Price>
</Item>
<Item Number="2">
<Part>B-43</Part>
<Quantity>600</Quantity>
<Price>3.99</Price>
</Item>
</SalesOrder>
該文檔映射為 清單 4 所示的對象。
清單 4. 層次化 XML 表示的單個銷售訂單 object SalesOrder {
number = 1234;
customer = "Gallagher IndustrIEs";
date = 29.10.00;
items = {ptrs to Item objects};
} / \
/ \
/ \
object Item { object Item {
number = 1; number = 2;
part = "A-10"; part = "B-43";
quantity = 12; quantity = 600;
price = 10.95; price = 3.99;
} }
該方法是層次化的,對數據映射來說很直觀。數據庫對象帶來了一些優點,其中包括:
數據庫獨立性:數據庫對象從根本上是獨立於數據庫創建的,不依賴於特定底層數據特性來提供其功能。這種獨立性使您可以使用數據庫對象迅速將應用程序構建從一種數據庫平台轉移到另一種數據庫平台,提供了很大的可伸縮性。
自動化的連接處理:自動化連接處理能夠連接、斷開和管理系統資源。對客戶機對象的抽象可以提供更好的控制和性能。
聲明性的引用完整性:通過直接在數據庫對象中嵌入訪問邏輯,可以獲得和使用存儲過程訪問數據庫同樣的好處,而且不依賴於特定平台。引用完整性成了數據庫獨立性,數據庫對象之間的復雜關系成了可移植性。比如,可以在數據庫對象中集成業務規則,讓訪問該對象的所有應用程序都保證遵守這些規則。
多層驗證:可以在對象或者其父對象上執行檢查。這樣就可以規范和驗證訪問、權限以及數據完整性。
避免內嵌 SQL:使用數據庫對象可以使應用程序避免內嵌 SQL 及其維護的困難和系統依賴性。如果應用程序只與其他 Java 對象交互,系統的設計就可以是完全面向對象的。
安全:可以確保與數據庫對象的任何交互的安全,並容易地保證數據安全。
映射方法論
實現對象-關系映射需要兩步。首先將 XML 模式(這裡使用 DTD)映射到對象模式,然後將對象模式映射到數據庫模式。也可以將這兩種映射合並成一個 DTD 到數據庫的映射,現在多數軟件都是這樣做的。
表 1 中的例子顯示的簡單元素類型 B、D 和 E 被映射到字符串,而復雜元素類型 A 和 C 被映射到類。在對象-關系映射的第一部分,A 和 C 的模型和屬性被映射到類 A 和 C 的屬性。A 的 C 的內容模型中對 B、D 和 E 的引用被映射為字符串。
表 1. 對象關系映射,第 1 部分 DTD 類 <!ELEMENT A (B, C)> <!ELEMENT B (#PCDATA)> <!ELEMENT C (D, E)> class A { String b; C c; } <!ELEMENT D (#PCDATA)> <!ELEMENT E (#PCDATA)> class C {String d; String e; }對象-關系映射的第二部分(參見表 2)中,類映射到表,標量屬性映射到列,指針/引用屬性映射到主鍵/外鍵關系。A 的內容模型中對 C 的引用被映射到 pointer/reference 類型的屬性,指向類 C 的對象,因為元素類型 C 被映射到類 C。
表 2. 對象關系映射,第 2 部分 類 表 class A {String b; C c; } Table A: Column b Column c_fk class C {String d; String e; } Table C: Column d Column e Column c_pk結束語
兩種映射都是對 XML 文檔中的數據 而不是對文檔本身建模。因此映射更適合於以數據為中心的文檔而不是以文檔為中心的文檔。雖然對象-關系映射是采用面向對象的技術,但是也不夠理想。基於表的映射根本不能處理混合內容,而從性能的角度看對象-關系映射可能效率很低。使用哪種方法都行,但是必須記住這些警告。