# 使用 SQLXML 对象

> 原文： [https://docs.oracle.com/javase/tutorial/jdbc/basics/sqlxml.html](https://docs.oracle.com/javase/tutorial/jdbc/basics/sqlxml.html)

`Connection`接口支持使用`createSQLXML`方法创建`SQLXML`对象。创建的对象不包含任何数据。可以通过调用`SQLXML`接口上的`setString`，`setBinaryStream`，`setCharacterStream`或`setResult`方法将数据添加到对象中。

涵盖以下主题：

*   [创建 SQLXML 对象](#creating_sqlxml)
*   [在 ResultSet 中检索 SQLXML 值](#retrieving_sqlxml)
*   [访问 SQLXML 对象数据](#accessing_sqlxml)
*   [存储 SQLXML 对象](#storing_sqlxml)
*   [初始化 SQLXML 对象](#initializing_sqlxml)
*   [发布 SQLXML 资源](#releasing_sqlxml)
*   [示例代码](#sample_code)

在以下摘录中，方法`Connection.createSQLXML`用于创建空`SQLXML`对象。 `SQLXML.setString`方法用于将数据写入已创建的`SQLXML`对象。

```
Connection con = DriverManager.getConnection(url, props);
SQLXML xmlVal = con.createSQLXML();
xmlVal.setString(val);

```

`SQLXML`数据类型的处理方式与更原始的内置类型相似。通过调用`ResultSet`或`CallableStatement`接口中的`getSQLXML`方法可以检索`SQLXML`值。

例如，以下摘录从`ResultSet` _rs_ 的第一列检索`SQLXML`值：

```
SQLXML xmlVar = rs.getSQLXML(1);

```

`SQLXML`对象至少在创建它们的事务持续时间内保持有效，除非调用它们的`free`方法。

`SQLXML`接口提供`getString`，`getBinaryStream`，`getCharacterStream`和`getSource`方法来访问其内部内容。以下摘录使用`getString`方法检索`SQLXML`对象的内容：

```
SQLXML xmlVal= rs.getSQLXML(1);
String val = xmlVal.getString();

```

`getBinaryStream`或`getCharacterStream`方法可用于获取可直接传递给 XML 解析器的`InputStream`或`Reader`对象。以下摘录从`SQLXML`对象获取`InputStream`对象，然后使用 DOM（文档对象模型）解析器处理流：

```
SQLXML sqlxml = rs.getSQLXML(column);
InputStream binaryStream = sqlxml.getBinaryStream();
DocumentBuilder parser = 
    DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document result = parser.parse(binaryStream);

```

`getSource`方法返回`javax.xml.transform.Source`对象。源用作 XML 解析器和 XSLT 转换器的输入。

以下摘录使用通过调用`getSource`方法返回的`SAXSource`对象从`SQLXML`对象检索和解析数据：

```
SQLXML xmlVal= rs.getSQLXML(1);
SAXSource saxSource = sqlxml.getSource(SAXSource.class);
XMLReader xmlReader = saxSource.getXMLReader();
xmlReader.setContentHandler(myHandler);
xmlReader.parse(saxSource.getInputSource());

```

与其他数据类型一样，`SQLXML`对象可以作为输入参数传递给`PreparedStatement`对象。方法`setSQLXML`使用`SQLXML`对象设置指定的`PreparedStatement`参数。

在下面的摘录中，`authorData`是`java.sql.SQLXML`接口的一个实例，其数据先前已初始化。

```
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO bio " +
                              "(xmlData, authId) VALUES (?, ?)");
pstmt.setSQLXML(1, authorData);
pstmt.setInt(2, authorId);

```

`updateSQLXML`方法可用于更新可更新结果集中的列值。

如果`SQLXML`对象的`java.xml.transform.Result`，`Writer`或`OutputStream`对象在调用`setSQLXML`或`updateSQLXML`之前尚未关闭，则会抛出`SQLException`。

`SQLXML`接口提供方法`setString`，`setBinaryStream`，`setCharacterStream`或`setResult`来初始化通过调用`Connection.createSQLXML`方法创建的`SQLXML`对象的内容。

以下摘录使用方法`setResult`返回`SAXResult`对象以填充新创建的`SQLXML`对象：

```
SQLXML sqlxml = con.createSQLXML();
SAXResult saxResult = sqlxml.setResult(SAXResult.class);
ContentHandler contentHandler = saxResult.getXMLReader().getContentHandler();
contentHandler.startDocument();

// set the XML elements and
// attributes into the result
contentHandler.endDocument();

```

以下摘录使用`setCharacterStream`方法获取`java.io.Writer`对象以初始化`SQLXML`对象：

```
SQLXML sqlxml = con.createSQLXML();
Writer out= sqlxml.setCharacterStream();
BufferedReader in = new BufferedReader(new FileReader("xml/foo.xml"));
String line = null;
while((line = in.readLine() != null) {
    out.write(line);
}

```

类似地，`SQLXML` `setString`方法可用于初始化`SQLXML`对象。

如果尝试在先前已初始化的`SQLXML`对象上调用`setString`，`setBinaryStream`，`setCharacterStream`和`setResult`方法，则将抛出`SQLException`。如果对同一`SQLXML`对象发生多次调用方法`setBinaryStream`，`setCharacterStream`和`setResult`，则抛出`SQLException`并返回先前`javax.xml.transform.Result`，`Writer`或`OutputStream` ]对象不受影响。

`SQLXML`对象至少在创建它们的事务期间保持有效。这可能导致应用程序在长时间运行的事务期间耗尽资源。应用程序可以通过调用`free`方法释放`SQLXML`资源。

在下面的摘录中，调用`method SQLXML.free`以释放为先前创建的`SQLXML`对象保留的资源。

```
SQLXML xmlVar = con.createSQLXML();
xmlVar.setString(val);
xmlVar.free();

```

MySQL 和 Java DB 及其各自的 JDBC 驱动程序不完全支持`SQLXML` JDBC 数据类型，如本节所述。但是，样本 `[RSSFeedsTable](gettingstarted.html)`演示了如何使用 MySQL 和 Java DB 处理 XML 数据。

The Coffee Break 的所有者关注来自各种网站的多个 RSS 源，其中包括餐馆和饮料行业的新闻。 RSS（Really Simple Syndication 或 Rich Site Summary）源是一个 XML 文档，其中包含一系列文章和相关元数据，例如每篇文章的发布日期和作者。所有者希望将这些 RSS 提要存储到数据库表中，包括来自 The Coffee Break 博客的 RSS 提要。

文件 `[rss-the-coffee-break-blog.xml](gettingstarted.html)`是来自 The Coffee Break 博客的示例 RSS 源。

样本`RSSFeedsTable`将 RSS 源存储在表`RSS_FEEDS`中，该表使用以下命令创建：

```
create table RSS_FEEDS
    (RSS_NAME varchar(32) NOT NULL,
    RSS_FEED_XML longtext NOT NULL,
    PRIMARY KEY (RSS_NAME));

```

MySQL 不支持 XML 数据类型。相反，此示例将 XML 数据存储在`LONGTEXT`类型的列中，该列是`CLOB` SQL 数据类型。 MySQL 有四种`CLOB`数据类型; `LONGTEXT`数据类型包含四个中最大的字符数。

方法 `[RSSFeedsTable.addRSSFeed](gettingstarted.html)`将 RSS 提要添加到`RSS_FEEDS`表。此方法的第一个语句将 RSS 提要（由此示例中的 XML 文件表示）转换为`org.w3c.dom.Document`类型的对象，该对象表示 DOM（文档对象模型）文档。此类以及包`javax.xml`中包含的类和接口包含使您能够操作 XML 数据内容的方法。例如，以下语句使用 XPath 表达式从`Document`对象检索 RSS 提要的标题：

```
Node titleElement =
    (Node)xPath.evaluate("/rss/channel/title[1]",
        doc, XPathConstants.NODE);

```

XPath 表达式`/rss/channel/title[1]`检索第一个`&lt;title&gt;`元素的内容。对于文件`rss-the-coffee-break-blog.xml`，这是字符串`The Coffee Break Blog`。

以下语句将 RSS 提要添加到表`RSS_FEEDS`：

```
// For databases that support the SQLXML
// data type, this creates a
// SQLXML object from
// org.w3c.dom.Document.

System.out.println("Adding XML file " + fileName);
String insertRowQuery =
    "insert into RSS_FEEDS " +
    "(RSS_NAME, RSS_FEED_XML) values " +
    "(?, ?)";
insertRow = con.prepareStatement(insertRowQuery);
insertRow.setString(1, titleString);

System.out.println("Creating SQLXML object with MySQL");
rssData = con.createSQLXML();
System.out.println("Creating DOMResult object");
DOMResult dom = (DOMResult)rssData.setResult(DOMResult.class);
dom.setNode(doc);

insertRow.setSQLXML(2, rssData);
System.out.println("Running executeUpdate()");
insertRow.executeUpdate();

```

`[RSSFeedsTable.viewTable](gettingstarted.html) `方法检索`RSS_FEEDS`的内容。对于每一行，该方法创建一个名为`doc`的`org.w3c.dom.Document`类型的对象，在该对象中将 XML 内容存储在`RSS_FEED_XML`列中。该方法检索 XML 内容并将其存储在名为`rssFeedXML`的`SQLXML`类型的对象中。 `rssFeedXML`的内容被解析并存储在`doc`对象中。

**注**：有关在 Java DB 中使用 XML 数据的更多信息，请参阅 [_Java DB 开发人员指南 _](http://docs.oracle.com/javadb/index_jdk8.html) 中的“XML 数据类型和运算符”部分。

样本`RSSFeedsTable`将 RSS 源存储在表`RSS_FEEDS`中，该表使用以下命令创建：

```
create table RSS_FEEDS
    (RSS_NAME varchar(32) NOT NULL,
    RSS_FEED_XML xml NOT NULL,
    PRIMARY KEY (RSS_NAME));

```

Java DB 支持 XML 数据类型，但它不支持`SQLXML` JDBC 数据类型。因此，您必须将任何 XML 数据转换为字符格式，然后使用 Java DB 运算符`XMLPARSE`将其转换为 XML 数据类型。

`[RSSFeedsTable.addRSSFeed](gettingstarted.html) `方法将 RSS 提要添加到`RSS_FEEDS`表。此方法的第一个语句将 RSS 提要（由此示例中的 XML 文件表示）转换为`org.w3c.dom.Document`类型的对象。这在[使用 MySQL 中的 XML 数据](#working-with-xml-data-in-mysql)一节中描述。

`[RSSFeedsTable.addRSSFeed](gettingstarted.html) `方法使用方法 `[JDBCTutorialUtilities.convertDocumentToString](gettingstarted.html)`将 RSS 提要转换为`String`对象。

Java DB 有一个名为`XMLPARSE`的运算符，它将字符串表示形式解析为 Java DB XML 值，由以下摘录演示：

```
String insertRowQuery =
    "insert into RSS_FEEDS " +
    "(RSS_NAME, RSS_FEED_XML) values " +
    "(?, xmlparse(document cast " +
    "(? as clob) preserve whitespace))";

```

`XMLPARSE`运算符要求您将 XML 文档的字符表示形式转换为 Java DB 可识别的字符串数据类型。在此示例中，它将其转换为`CLOB`数据类型。有关 Apache Xalan 和 Java DB 要求的更多信息，请参见[入门](gettingstarted.html)和 Java DB 文档。

方法 `[RSSFeedsTable.viewTable](gettingstarted.html)`检索`RSS_FEEDS`的内容。由于 Java DB 不支持 JDBC 数据类型`SQLXML`，因此必须将 XML 内容检索为字符串。 Java DB 有一个名为`XMLSERIALIZE`的运算符，它将 XML 类型转换为字符类型：

```
String query =
    "select RSS_NAME, " +
    "xmlserialize " +
    "(RSS_FEED_XML as clob) " +
    "from RSS_FEEDS";

```

与`XMLPARSE`运算符一样，`XMLSERIALIZE`运算符要求在您的 Java 类路径中列出 Apache Xalan。