J2EE 開發人員通常需要在關系數據庫中存儲 XML 文檔以及從數據庫中檢索 XML 文檔,以獲得元素值和屬性值。目前,只有特定于供應商的技術和數據類型可用于在關系數據庫中存儲 XML 文檔。例如 IBM DB2 Universal Database™ (UDB) 提供了 DB2 XML Extender 和 XML 用戶定義類型 (UDT) 來存儲 XML 文檔。用于 XML 類型列的標準數據類型和對應于 XML 類型列的 Java 數據類型將促進關系數據庫中 XML 文檔的存儲和檢索。SQL:2003 標準支持這樣一種數據類型:新 XML
數據類型,以便在關系數據庫中存儲 XML 文檔。借助 XML
數據類型,您可以在類似于其他數據類型的數據庫表列中存儲 XML 文檔。DB2 Viper(即 DB2 UDB Version 9.1)支持 XML
數據類型。Java Database Connectivity (JDBC) 4.0 規范支持 SQL:2003 標準。
初步設置
在開始之前,確保擁有必要的組件。SQLXML
是一種 JDBC 4.0 數據類型。因為 SQLXML
數據類型是在 Sun 提供的 Java SE 6 Development Kit (JDK) 6.0 Beta 中實現的,所以您需要安裝它。另一個要求是創建一個 SQLXML
類型對象,該對象是一個支持 XML
數據類型的關系數據庫。DB2 Viper(即 DB2 UDB Version 9.1)支持 XML
數據類型。要運行本文中包含的示例應用程序 SQLXMLDB.java
,需要安裝 DB2 Viper 數據庫,并創建示例 DB2 數據庫實例 Sample
。JDK 6.0 Beta、DB2 Viper 和 SQLXMLDB.java 可以分別從 參考資料 和 下載 中獲得。
您還需要一個 JDBC 4.0 驅動程序,但 DB2 UDB 目前并沒有提供 JDBC 4.0 驅動程序,要運行帶有 DB2 JDBC 3.0 驅動程序的 SQLXMLDB.java 并確定 DB2 數據庫是否支持 XML
數據類型,需要將 JAR 文件 C:/Program Files/IBM/SQLLIB/java/db2jclearcase/" target="_blank" >cc.jar
和 C:/Program Files/IBM/SQLLIB/java/db2jcc_license_cu.jar
添加到 Classpath 中。當 JDBC 4.0 驅動程序變得可用時,就可以利用 SQLXML
API 運行 SQLXMLDB.java 了。當 JDBC 4.0 驅動程序變得可用時,本文將被更新。
開始
SQLXML
Java 數據類型允許您將 XML
類型數據庫列映射到 Java 數據類型。在 JDBC 4.0 規范中,java.sql.Connection
接口可以創建一個最初沒有任何數據的 SQLXML
對象,但您可以用 setString(String)
方法或 createXMLStreamWriter()
方法添加數據。SQLXML
對象可利用 getSQLXML(int columnIndex)
方法或 getSQLXML(String columnName)
方法從 ResultSet
或 CallableStatement
對象中獲得??梢杂?getString()
方法或 createXMLStreamReader()
方法檢索 SQLXML
對象中的數據,還可以用 PreparedStatement
接口的 setSQLXML(int parameterIndex, SQLXML sqlXML)
方法在類似于其他任何數據類型的類型 XML
的數據庫表列中存儲 SQLXML
對象。
清單 1 顯示了一個您可以創建的 XML 文檔的例子,即 catalog.xml
:
|
![]() ![]() |
![]()
|
選擇數據庫
需要一個關系數據庫來支持 XML
數據類型存儲 XML 文檔,不是所有的數據庫都支持 XML
數據類型。要確定數據庫是否支持該數據庫類型,需要從 Connection
對象中獲得數據庫元數據。例如,要測試 DB2 Viper 是否支持 XML
數據類型,需要加載并注冊 com.ibm.db2.jcc.DB2Driver
JDBC 驅動程序,即 DB2 JDBC Type 4 驅動程序:
|
為 DB2 UDB 數據庫指定連接 URL。DB2 UDB Type 4 驅動程序的格式為 jdbc:db2://<server>:<port>/<database>
。在此連接 URL 中,<server>
是 DB2 UDB 服務器名稱,<port>
是 DB2 數據庫端口,而 <database>
是 DB2 數據庫實例。DB2 UDB 數據庫的連接 URL 是:
|
利用 DriverManager
的靜態方法 getConnection()
獲得與數據庫的 Connection
:
|
接下來,從 Connection
對象獲得數據庫元數據:
|
然后,利用 getTypeInfo()
方法獲得受數據庫支持的數據類型:
|
在數據類型結果集上進行迭代并輸出 TYPE_NAME
列:
|
如果數據庫支持 XML
數據類型,則 XML TYPE_NAME
獲得輸出。由于 DB2 Viper 數據庫支持 XML
數據類型,所以運行 SQLXMLDB.java
應用程序所得到的輸出包括 XML
數據類型,如下所示:
|
創建 SQLXML 對象
這一節將討論創建 SQLXML
對象的過程。首先,導入 java.sql package 和 javax.xml.stream 包。javax.xml.stream 包具有實例化 SQLXML
對象和獲得 SQLXML
對象中的數據所需的 XMLStreamWriter
和 XMLStreamReader
接口。
|
XML 文檔在類型為 XML
的數據庫表列中的 Java 表示是 SQLXML
。要創建一個將存儲在 XML
類型列中的 XML 文檔,需要使用 createSQLXML()
方法從 Connection
對象創建一個 SQLXML
對象:
|
用 createSQLXML()
方法創建的 SQLXML
對象不包含任何數據。下一節 將展示如何將數據添加到 SQLXML
對象中。
初始化 SQLXML 對象
您可以使用 XMLStreamWriter
對象創建一個 XML 文檔??梢允褂?createXMLStreamWriter()
方法從 SQLXML
對象中創建 XMLStreamWriter
對象:
|
如果調用 createXMLStreamWriter()
方法,而不是使用相同的 SQLXML
對象,則會拋出 SQLException
,并且先前返回的 XMLStreamWriter
對象不受影響。
用 writeStartDocument(String encoding, String version)
方法添加 XML 文檔的開始部分。writeStartDocument()
方法中指定的編碼并沒有設置 XML 文檔輸出的編碼;指定的編碼只設置 XML 聲明中的編碼。XMLStreamWriter
接口還包括 writeStartDocument()
方法和 writeStartDocument(String version)
方法,前者用于在沒有指定編碼和版本的情況下創建 XML 文檔,后者用于在提供版本的情況下創建 XML 文檔:
|
用 writeStartElement(String localName)
方法(如下面代碼片段所示)添加根元素 catalog
的開始部分。使用 writeStartElement(String prefix, String localName, String namespaceURI)
方法根據名稱空間和前綴創建一個元素。使用 writeEmptyElement(String localName)
方法可生成一個空元素:
|
用 writeAttribute(String localName, String value)
方法添加 title
屬性,如下面代碼片段所示。同樣,還可以添加 publisher
屬性。如果屬性有一個名稱空間前綴,則使用方法 writeAttribute(String prefix, String namespaceURI, String localName, String value)
:
|
類似地,還可以添加 journal
元素及其屬性 date
:
|
添加一個 article
元素和一個 title
元素:
|
用 writeCharacters(String text)
方法將文本添加到 title
元素中,如下面代碼片段所示。此外,可以使用 writeCharacters(char[] text,int start,int len)
方法從 char[]
數組中添加文本。
|
確保 start
元素有一個相應的 end
元素標記。使用 writeEndElement()
方法添加一個 end
元素:
|
writeEndElement()
方法沒有像 writeStartElement()
方法那樣指定元素的本地名稱。類似地,可以添加其他元素來創建 清單 1 中所示的 XML 文檔。要完成 XML 文檔,請調用 writeEndDocument()
方法。此外,請關閉 XMLStreamWriter
對象:
|
您還可以使用 SQLXML
接口的 setString(String)
方法將 XML 文檔從 XML 字符串添加到 SQLXML
對象中,如 清單 2 所示。如果在前面已初始化的 SQLXML
對象上調用 setString(String)
方法,則會拋出 SQLException
。
|
下一節 解釋如何將創建的 SQLXML
對象存儲到數據庫中。
存儲 SQLXML 對象
SQLXML
Java 數據類型存儲在 XML 文檔中,就像其他任何 Java 數據類型那樣。首先,用 XML
類型列創建一個數據庫表??梢越柚?SQL 命令行工具或 JDBC API,用 XML
類型列創建數據庫表。要用 JDBC 創建數據庫表,需要從 Connection
對象中獲得一個 Statement
對象:
|
用 XML
類型列創建一個數據庫表,比如 Catalog
:
|
將 前一節 中創建的 SQLXML
對象添加到數據庫中。創建一個 PreparedStatement
對象,以便將值添加到數據庫表 Catalog
中。PreparedStatement
由 INSERT
SQL 語句和用來添加到數據庫的那些值的參數標志符組成:
|
用 setInt(int parameterIndex, int value)
方法設置 int
值,用 PreparedStatement
接口的 setSQLXML(int parameterIndex, SQLXML value)
方法設置 SQLXML
值,如下所示。如果沒有在調用 setSQLXML()
方法前關閉 XMLStreamWriter
對象,則會拋出 SQLException
。
|
用 executeUpdate()
方法更新數據庫:
|
SQLXML
對象至少在創建 SQLXML
對象期間是有效的。如果不使用某個 SQLXML
對象,則可以使用 free()
方法釋放這個 SQLXML
對象資源:
|
更新 SQLXML 對象
JDK 6.0 Beta 還在 ResultSet
接口中提供了一些 updater 方法來更新 SQLXML
值。updater 方法 updateSQLXML(int columnIndex, SQLXML sqlXML)
和 updateSQLXML(String columnName, SQLXML sqlXML)
可修改當前行中的 SQLXML
值或 ResultSet
對象的插入行。例如,要在 ResultSet
對象中添加新行,需要獲得一個不可更新的 ResultSet
類型的 Statement
對象:
|
從數據庫表 Catalog
獲得一個 ResultSet
,該表有一個 XML
類型的列??梢砸苿?ResultSet
游標來插入一個行。還可以使用 updateSQLXML()
方法添加 SQLXML
列值。updateSQLXML()
方法不更新數據庫。要更新數據庫,需要調用 insertRow()
方法:
|
此外,要在可滾動的 ResultSet
中從當前行更新 ResultSet
,需要使用 absolute(int)
或 relative(int)
方法移動到 ResultSet
行??梢允褂?updater 方法之一修改 SQLXML
值。使用 updateRow()
方法更新數據庫:
|
如果沒有在調用 updater 方法之前關閉 XMLStreamWriter
對象,則會拋出 SQLException
。
從 ResultSet 對象檢索 SQLXML 對象
以 SQLXML
數據類型的形式檢索 XML
數據庫類型列值。為 SELECT
SQL 查詢創建一條 PreparedStatement
,以便從數據庫表 Catalog
中獲得 ResultSet
,如下面代碼片段所示。SQL 語句有一個用于 CatalogId
值的參數標志符。
|
指定將從中檢索 XML 文檔的 CatalogId
值:
|
用 executeQuery()
方法獲得一個結果集:
|
使用 ResultSet
接口的方法 getSQLXML(int columnIndex)
或 getSQLXML(String columnName)
獲得用于 XML 類型 Catalog
列的 SQLXML
對象:
|
要在 SQLXML
對象中輸出 XML 文檔,可能需要使用 SQLXML
接口的 getString()
方法:
|
訪問 SQLXML 對象
使用 XMLStreamReader
接口讀取具有事件迭代器的 SQLXML
對象中的 XML 文檔。從將被導航的 SQLXML
對象中創建一個 XMLStreamReader
對象:
|
下一個解析事件是用 next()
方法獲得的:
|
next()
方法返回一個對應于 XMLStreamConstants
常量的 int
值。表 1 列出了 next()
方法的返回值。
解析事件 | 描述 |
---|---|
ATTRIBUTE | 指定一個屬性 |
CDATA | CData 部分 |
CHARACTERS | 文本 |
NOTATION_DECLARATION | 指定一個符號聲明 |
COMMENT | XML 文檔注釋 |
PROCESSING_INSTRUCTION | 指定一個處理指令 |
START_DOCUMENT | 指定文檔的開始處 |
START_ELEMENT | 指定元素的開始處 |
END_ELEMENT | 指定元素的結尾處 |
ENTITY_DECLARATION | 指定一個實體聲明 |
ENTITY_REFERENCE | 指定一個實體引用 |
NAMESPACE | 指定一個名稱空間聲明 |
SPACE | 指定一個可忽略的空白 |
END_DOCUMENT | 指定文檔的結尾處 |
DTD | 指定一個 DTD |
如果返回值是 START_ELEMENT
,則解析事件指示某一元素已經被解析??梢允褂梅椒?getLocalName()
、getPrefix()
、getNamespaceURI()
獲得本地名稱、前綴和名稱空間元素:
|
可以使用 getAttributeCount()
方法獲得元素中的屬性總數。還可以在屬性上進行迭代,使用 getAttributeLocalName()
方法獲得屬性本地名稱,使用 getAttributeValue()
方法獲得屬性值,使用 getAttributePrefix()
方法獲得屬性前綴,以及使用 getAttributeNamespace()
方法獲得屬性名稱空間:
|
如果解析事件的類型為 CHARACTERS
,可使用 getText()
方法獲得解析事件的文本:
|
結束語
SQLXML
數據類型為數據庫類型 XML
提供了數據庫到 Java 的映射工具。您可以對任何支持 XML 數據類型并提供 JDBC 4.0 驅動程序的數據庫使用 SQLXML
數據類型。特定于供應商的 XML-to-SQL API 對 SQLXML
不是必需的。SQLXML
API 將包含在 JDK 6.0 中。DB2 Viper 支持 XML
數據類型。
![]() ![]() |
![]()
|
下載
描述 | 名字 | 大小 | 下載方法 |
---|---|---|---|
Sample application SQLXMLDB.java | x-sqlxmldb.zip | 3KB | HTTP |