使用 WebRowSet 对象
原文: https://docs.oracle.com/javase/tutorial/jdbc/basics/webrowset.html
WebRowSet对象非常特殊,因为除了提供CachedRowSet对象的所有功能外,它还可以将自身编写为 XML 文档,还可以读取该 XML 文档以将其自身转换回WebRowSet对象。由于 XML 是不同企业可以相互通信的语言,因此它已成为 Web 服务通信的标准。因此,WebRowSet对象通过使 Web 服务能够以 XML 文档的形式从数据库发送和接收数据来满足实际需求。
涵盖以下主题:
Coffee Break 公司已经扩展到在线销售咖啡。用户从 Coffee Break 网站点击咖啡。通过从公司数据库获取最新信息,定期更新价目表。本节演示如何使用WebRowSet对象和单个方法调用将价格数据作为 XML 文档发送。
使用参考实现WebRowSetImpl中定义的默认构造器创建新的WebRowSet对象,如以下代码行所示:
WebRowSet priceList = new WebRowSetImpl();
虽然priceList对象尚无数据,但它具有BaseRowSet对象的默认属性。它的SyncProvider对象首先设置为RIOptimisticProvider实现,这是所有断开连接的RowSet对象的默认设置。但是,WebRowSet实现将SyncProvider对象重置为RIXMLProvider实现。
您可以使用RowSetProvider类创建的RowSetFactory实例来创建WebRowSet对象。有关详细信息,请参阅使用中的 RowSetFactory 接口使用 JdbcRowSet 对象。
Coffee Break 总部定期向其网站发送价目表更新。有关WebRowSet对象的信息将显示一种可以在 XML 文档中发送最新价目表的方法。
价格表包含表COFFEES中COF_NAME和PRICE列中的数据。以下代码片段设置所需的属性,并使用价目表数据填充priceList对象:
public void getPriceList(String username, String password) {priceList.setCommand("SELECT COF_NAME, PRICE FROM COFFEES");priceList.setURL("jdbc:mySubprotocol:myDatabase");priceList.setUsername(username);priceList.setPassword(password);priceList.execute();// ...}
此时,除了默认属性外,priceList对象还包含COFFEES表中COF_NAME和PRICE列中的数据以及有关这两列的元数据。
要将WebRowSet对象写为 XML 文档,请调用方法writeXml。要将 XML 文档的内容读入WebRowSet对象,请调用方法readXml。这两种方法都在后台完成它们的工作,这意味着除了结果之外的所有内容对您来说都是不可见的。
使用 writeXml 方法
方法writeXml将调用它的WebRowSet对象写为表示其当前状态的 XML 文档。它将此 XML 文档写入您传递给它的流。流可以是OutputStream对象,例如FileOutputStream对象,或Writer对象,例如FileWriter对象。如果传递方法writeXml和OutputStream对象,则将以字节为单位写入,可以处理所有类型的数据;如果你传递一个Writer对象,你将写入字符。以下代码演示了将WebRowSet对象priceList作为 XML 文档写入FileOutputStream对象oStream:
java.io.FileOutputStream oStream =new java.io.FileOutputStream("priceList.xml");priceList.writeXml(oStream);
以下代码将表示priceList的 XML 文档写入FileWriter对象writer而不是OutputStream对象。 FileWriter类是用于将字符写入文件的便捷类。
java.io.FileWriter writer =new java.io.FileWriter("priceList.xml");priceList.writeXml(writer);
方法的另外两个版本writeXml允许您在将ResultSet对象的内容写入流之前使用ResultSet对象的内容填充该对象。在下面的代码行中,方法writeXml将ResultSet对象rs的内容读入priceList对象,然后将priceList作为 XML 文档写入FileOutputStream对象oStream。
priceList.writeXml(rs, oStream);
在下一行代码中,writeXml方法使用rs的内容填充priceList,但它将 XML 文档写入FileWriter对象而不是OutputStream对象:
priceList.writeXml(rs, writer);
使用 readXml 方法
方法readXml解析 XML 文档以构造 XML 文档描述的WebRowSet对象。与方法writeXml类似,您可以传递readXml InputStream对象或Reader对象,从中读取 XML 文档。
java.io.FileInputStream iStream =new java.io.FileInputStream("priceList.xml");priceList.readXml(iStream);java.io.FileReader reader = newjava.io.FileReader("priceList.xml");priceList.readXml(reader);
请注意,您可以将 XML 描述读入新的WebRowSet对象或调用writeXml方法的相同WebRowSet对象。在场景中,价格表信息从总部发送到网站,您将使用新的WebRowSet对象,如以下代码行所示:
WebRowSet recipient = new WebRowSetImpl();java.io.FileReader reader =new java.io.FileReader("priceList.xml");recipient.readXml(reader);
RowSet对象不仅仅是它们包含的数据。它们还具有有关其列的属性和元数据。因此,表示WebRowSet对象的 XML 文档除了其数据之外还包括该其他信息。此外,XML 文档中的数据包括当前值和原始值。 (回想一下原始值是在最近的数据更改之前存在的值。这些值是检查数据库中相应值是否已更改所必需的,从而产生了应该持久保存值的冲突:放入RowSet对象的新值或其他人放入数据库的新值。)
WebRowSet XML Schema 本身就是一个 XML 文档,它定义了表示WebRowSet对象的 XML 文档将包含的内容以及必须呈现它的格式。发件人和收件人都使用此架构,因为它告诉发件人如何编写 XML 文档(表示WebRowSet对象)和收件人如何解析 XML 文档。因为实际的写入和读取是通过方法writeXml和readXml的实现在内部完成的,所以作为用户,您不需要了解 WebRowSet XML Schema 文档中的内容。
XML 文档包含分层结构中的元素和子元素。以下是描述WebRowSet对象的 XML 文档中的三个主要元素:
元素标签用信号通知元素的开头和结尾。例如,<properties>标记表示属性元素的开头,</properties>标记表示其结束。 <map/>标签是说明地图子元素(属性元素中的一个子元素)尚未赋值的简写方式。以下示例 XML 文档使用间距和缩进来使其更易于阅读,但这些不在实际的 XML 文档中使用,其中间距并不意味着什么。
接下来的三节将向您展示在样例 WebRowSetSample.java 中创建的WebRowSet priceList对象的三个主要元素。
在priceList对象上调用方法writeXml将生成描述priceList的 XML 文档。此 XML 文档的属性部分如下所示:
<properties><command>select COF_NAME, PRICE from COFFEES</command><concurrency>1008</concurrency><datasource><null/></datasource><escape-processing>true</escape-processing><fetch-direction>1000</fetch-direction><fetch-size>0</fetch-size><isolation-level>2</isolation-level><key-columns>1</key-columns><map></map><max-field-size>0</max-field-size><max-rows>0</max-rows><query-timeout>0</query-timeout><read-only>true</read-only><rowset-type>ResultSet.TYPE_SCROLL_INSENSITIVE</rowset-type><show-deleted>false</show-deleted><table-name>COFFEES</table-name><url>jdbc:mysql://localhost:3306/testdb</url><sync-provider><sync-provider-name>com.sun.rowset.providers.RIOptimisticProvider</sync-provider-name><sync-provider-vendor>Sun Microsystems Inc.</sync-provider-vendor><sync-provider-version>1.0</sync-provider-version><sync-provider-grade>2</sync-provider-grade><data-source-lock>1</data-source-lock></sync-provider></properties>
请注意,某些属性没有任何价值。例如,datasource属性用<datasource/>标签表示,这是说<datasource></datasource>的简写方式。没有给出值,因为设置了url属性。建立的任何连接都将使用此 JDBC URL 完成,因此不需要设置DataSource对象。此外,未列出username和password属性,因为它们必须保密。
描述WebRowSet对象的 XML 文档的元数据部分包含有关该WebRowSet对象中的列的信息。以下显示了WebRowSet对象priceList的这一部分。因为priceList对象有两列,所以描述它的 XML 文档有两个<column-definition>元素。每个<column-definition>元素都有子元素,提供有关所描述列的信息。
<metadata>21<auto-increment>false</auto-increment><case-sensitive>false</case-sensitive><currency>false</currency><nullable>0</nullable><signed>false</signed><searchable>true</searchable>32COF_NAMECOF_NAME<schema-name></schema-name>320<table-name>coffees</table-name><catalog-name>testdb</catalog-name>12VARCHAR2<auto-increment>false</auto-increment><case-sensitive>true</case-sensitive><currency>false</currency><nullable>0</nullable><signed>true</signed><searchable>true</searchable>12PRICEPRICE<schema-name></schema-name>102<table-name>coffees</table-name><catalog-name>testdb</catalog-name>3DECIMAL</metadata>
从此元数据部分,您可以看到每行中有两列。第一列是COF_NAME,其中包含VARCHAR类型的值。第二列是PRICE,它保存REAL类型的值,依此类推。请注意,列类型是数据源中使用的数据类型,而不是 Java 编程语言中的类型。要获取或更新COF_NAME列中的值,可以使用方法getString或updateString,驱动程序会像往常一样转换为VARCHAR类型。
数据部分给出WebRowSet对象每行中每列的值。如果已填充priceList对象并且未对其进行任何更改,则 XML 文档的数据元素将如下所示。在下一节中,您将看到在修改priceList对象中的数据时 XML 文档如何更改。
对于每一行,都有一个<currentRow>元素,因为priceList有两列,每个<currentRow>元素包含两个<columnValue>元素。
<data><currentRow>Colombian7.99</currentRow><currentRow>Colombian_Decaf8.99</currentRow><currentRow>Espresso9.99</currentRow><currentRow>French_Roast8.99</currentRow><currentRow>French_Roast_Decaf9.99</currentRow></data>
您对WebRowSet对象的更改方式与对CachedRowSet对象的更改方式相同。但是,与CachedRowSet对象不同,WebRowSet对象会跟踪更新,插入和删除,以便writeXml方法可以同时写入当前值和原始值。接下来的三个部分演示了对数据的更改,并显示了每次更改后描述WebRowSet对象的 XML 文档的样子。您不必对 XML 文档做任何事情;对它的任何更改都是自动进行的,就像编写和读取 XML 文档一样。
插入行
如果 Coffee Break 连锁店的所有者想要在价目表中添加新咖啡,则代码可能如下所示:
priceList.absolute(3);priceList.moveToInsertRow();priceList.updateString(COF_NAME, "Kona");priceList.updateFloat(PRICE, 8.99f);priceList.insertRow();priceList.moveToCurrentRow();
在参考实现中,紧接在当前行之后进行插入。在前面的代码片段中,当前行是第三行,因此新行将在第三行之后添加并成为新的第四行。为了反映这种插入,XML 文档将在<data>元素中的第三个<currentRow>元素之后添加以下<insertRow>元素。
<insertRow>元素看起来类似于以下内容。
<insertRow>Kona8.99</insertRow>
删除行
店主决定 Espresso 销售不足,应该从咖啡休息店出售的咖啡中取出。因此,所有者想要从价目表中删除 Espresso。 Espresso 位于priceList对象的第三行,因此以下代码行将其删除:
priceList.absolute(3); priceList.deleteRow();
以下<deleteRow>元素将出现在 XML 文档的数据部分中的第二行之后,表示已删除第三行。
<deleteRow>Espresso9.99</deleteRow>
修改行
店主进一步决定哥伦比亚咖啡的价格过于昂贵,并希望将其降低至每磅 6.99 美元。以下代码将哥伦比亚咖啡的新价格设定为每磅 6.99 美元,这是第一排的价格:
priceList.first();priceList.updateFloat(PRICE, 6.99);
XML 文档将在提供新值的<updateRow>元素中反映此更改。第一列的值没有改变,因此只有第二列的<updateValue>元素:
<currentRow>Colombian7.99<updateRow>6.99</updateRow></currentRow>
此时,通过插入行,删除行以及修改行,priceList对象的 XML 文档如下所示:
<data><insertRow>Kona8.99</insertRow><currentRow>Colombian7.99<updateRow>6.99</updateRow></currentRow><currentRow>Colombian_Decaf8.99</currentRow><deleteRow>Espresso9.99</deleteRow><currentRow>French_Roast8.99</currentRow><currentRow>French_Roast_Decaf9.99</currentRow></data>
WebRowSet 代码示例
示例[WebRowSetSample.java]($docs-gettingstarted.html)演示了此页面上描述的所有功能。
