使用 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对象,如以下代码行所示:

  1. WebRowSet priceList = new WebRowSetImpl();

虽然priceList对象尚无数据,但它具有BaseRowSet对象的默认属性。它的SyncProvider对象首先设置为RIOptimisticProvider实现,这是所有断开连接的RowSet对象的默认设置。但是,WebRowSet实现将SyncProvider对象重置为RIXMLProvider实现。

您可以使用RowSetProvider类创建的RowSetFactory实例来创建WebRowSet对象。有关详细信息,请参阅使用中的 RowSetFactory 接口使用 JdbcRowSet 对象。

Coffee Break 总部定期向其网站发送价目表更新。有关WebRowSet对象的信息将显示一种可以在 XML 文档中发送最新价目表的方法。

价格表包含表COFFEESCOF_NAMEPRICE列中的数据。以下代码片段设置所需的属性,并使用价目表数据填充priceList对象:

  1. public void getPriceList(String username, String password) {
  2. priceList.setCommand("SELECT COF_NAME, PRICE FROM COFFEES");
  3. priceList.setURL("jdbc:mySubprotocol:myDatabase");
  4. priceList.setUsername(username);
  5. priceList.setPassword(password);
  6. priceList.execute();
  7. // ...
  8. }

此时,除了默认属性外,priceList对象还包含COFFEES表中COF_NAMEPRICE列中的数据以及有关这两列的元数据。

要将WebRowSet对象写为 XML 文档,请调用方法writeXml。要将 XML 文档的内容读入WebRowSet对象,请调用方法readXml。这两种方法都在后台完成它们的工作,这意味着除了结果之外的所有内容对您来说都是不可见的。

使用 writeXml 方法

方法writeXml将调用它的WebRowSet对象写为表示其当前状态的 XML 文档。它将此 XML 文档写入您传递给它的流。流可以是OutputStream对象,例如FileOutputStream对象,或Writer对象,例如FileWriter对象。如果传递方法writeXmlOutputStream对象,则将以字节为单位写入,可以处理所有类型的数据;如果你传递一个Writer对象,你将写入字符。以下代码演示了将WebRowSet对象priceList作为 XML 文档写入FileOutputStream对象oStream

  1. java.io.FileOutputStream oStream =
  2. new java.io.FileOutputStream("priceList.xml");
  3. priceList.writeXml(oStream);

以下代码将表示priceList的 XML 文档写入FileWriter对象writer而不是OutputStream对象。 FileWriter类是用于将字符写入文件的便捷类。

  1. java.io.FileWriter writer =
  2. new java.io.FileWriter("priceList.xml");
  3. priceList.writeXml(writer);

方法的另外两个版本writeXml允许您在将ResultSet对象的内容写入流之前使用ResultSet对象的内容填充该对象。在下面的代码行中,方法writeXmlResultSet对象rs的内容读入priceList对象,然后将priceList作为 XML 文档写入FileOutputStream对象oStream

  1. priceList.writeXml(rs, oStream);

在下一行代码中,writeXml方法使用rs的内容填充priceList,但它将 XML 文档写入FileWriter对象而不是OutputStream对象:

  1. priceList.writeXml(rs, writer);

使用 readXml 方法

方法readXml解析 XML 文档以构造 XML 文档描述的WebRowSet对象。与方法writeXml类似,您可以传递readXml InputStream对象或Reader对象,从中读取 XML 文档。

  1. java.io.FileInputStream iStream =
  2. new java.io.FileInputStream("priceList.xml");
  3. priceList.readXml(iStream);
  4. java.io.FileReader reader = new
  5. java.io.FileReader("priceList.xml");
  6. priceList.readXml(reader);

请注意,您可以将 XML 描述读入新的WebRowSet对象或调用writeXml方法的相同WebRowSet对象。在场景中,价格表信息从总部发送到网站,您将使用新的WebRowSet对象,如以下代码行所示:

  1. WebRowSet recipient = new WebRowSetImpl();
  2. java.io.FileReader reader =
  3. new java.io.FileReader("priceList.xml");
  4. recipient.readXml(reader);

RowSet对象不仅仅是它们包含的数据。它们还具有有关其列的属性和元数据。因此,表示WebRowSet对象的 XML 文档除了其数据之外还包括该其他信息。此外,XML 文档中的数据包括当前值和原始值。 (回想一下原始值是在最近的数据更改之前存在的值。这些值是检查数据库中相应值是否已更改所必需的,从而产生了应该持久保存值的冲突:放入RowSet对象的新值或其他人放入数据库的新值。)

WebRowSet XML Schema 本身就是一个 XML 文档,它定义了表示WebRowSet对象的 XML 文档将包含的内容以及必须呈现它的格式。发件人和收件人都使用此架构,因为它告诉发件人如何编写 XML 文档(表示WebRowSet对象)和收件人如何解析 XML 文档。因为实际的写入和读取是通过方法writeXmlreadXml的实现在内部完成的,所以作为用户,您不需要了解 WebRowSet XML Schema 文档中的内容。

XML 文档包含分层结构中的元素和子元素。以下是描述WebRowSet对象的 XML 文档中的三个主要元素:

元素标签用信号通知元素的开头和结尾。例如,<properties>标记表示属性元素的开头,</properties>标记表示其结束。 <map/>标签是说明地图子元素(属性元素中的一个子元素)尚未赋值的简写方式。以下示例 XML 文档使用间距和缩进来使其更易于阅读,但这些不在实际的 XML 文档中使用,其中间距并不意味着什么。

接下来的三节将向您展示在样例 WebRowSetSample.java 中创建的WebRowSet priceList对象的三个主要元素。

priceList对象上调用方法writeXml将生成描述priceList的 XML 文档。此 XML 文档的属性部分如下所示:

  1. <properties>
  2. <command>
  3. select COF_NAME, PRICE from COFFEES
  4. </command>
  5. <concurrency>1008</concurrency>
  6. <datasource><null/></datasource>
  7. <escape-processing>true</escape-processing>
  8. <fetch-direction>1000</fetch-direction>
  9. <fetch-size>0</fetch-size>
  10. <isolation-level>2</isolation-level>
  11. <key-columns>
  12. 1
  13. </key-columns>
  14. <map>
  15. </map>
  16. <max-field-size>0</max-field-size>
  17. <max-rows>0</max-rows>
  18. <query-timeout>0</query-timeout>
  19. <read-only>true</read-only>
  20. <rowset-type>
  21. ResultSet.TYPE_SCROLL_INSENSITIVE
  22. </rowset-type>
  23. <show-deleted>false</show-deleted>
  24. <table-name>COFFEES</table-name>
  25. <url>jdbc:mysql://localhost:3306/testdb</url>
  26. <sync-provider>
  27. <sync-provider-name>
  28. com.sun.rowset.providers.RIOptimisticProvider
  29. </sync-provider-name>
  30. <sync-provider-vendor>
  31. Sun Microsystems Inc.
  32. </sync-provider-vendor>
  33. <sync-provider-version>
  34. 1.0
  35. </sync-provider-version>
  36. <sync-provider-grade>
  37. 2
  38. </sync-provider-grade>
  39. <data-source-lock>1</data-source-lock>
  40. </sync-provider>
  41. </properties>

请注意,某些属性没有任何价值。例如,datasource属性用<datasource/>标签表示,这是说<datasource&gt;&lt;/datasource>的简写方式。没有给出值,因为设置了url属性。建立的任何连接都将使用此 JDBC URL 完成,因此不需要设置DataSource对象。此外,未列出usernamepassword属性,因为它们必须保密。

描述WebRowSet对象的 XML 文档的元数据部分包含有关该WebRowSet对象中的列的信息。以下显示了WebRowSet对象priceList的这一部分。因为priceList对象有两列,所以描述它的 XML 文档有两个<column-definition>元素。每个<column-definition>元素都有子元素,提供有关所描述列的信息。

  1. <metadata>
  2. 2
  3. 1
  4. <auto-increment>false</auto-increment>
  5. <case-sensitive>false</case-sensitive>
  6. <currency>false</currency>
  7. <nullable>0</nullable>
  8. <signed>false</signed>
  9. <searchable>true</searchable>
  10. 32
  11. COF_NAME
  12. COF_NAME
  13. <schema-name></schema-name>
  14. 32
  15. 0
  16. <table-name>coffees</table-name>
  17. <catalog-name>testdb</catalog-name>
  18. 12
  19. VARCHAR
  20. 2
  21. <auto-increment>false</auto-increment>
  22. <case-sensitive>true</case-sensitive>
  23. <currency>false</currency>
  24. <nullable>0</nullable>
  25. <signed>true</signed>
  26. <searchable>true</searchable>
  27. 12
  28. PRICE
  29. PRICE
  30. <schema-name></schema-name>
  31. 10
  32. 2
  33. <table-name>coffees</table-name>
  34. <catalog-name>testdb</catalog-name>
  35. 3
  36. DECIMAL
  37. </metadata>

从此元数据部分,您可以看到每行中有两列。第一列是COF_NAME,其中包含VARCHAR类型的值。第二列是PRICE,它保存REAL类型的值,依此类推。请注意,列类型是数据源中使用的数据类型,而不是 Java 编程语言中的类型。要获取或更新COF_NAME列中的值,可以使用方法getStringupdateString,驱动程序会像往常一样转换为VARCHAR类型。

数据部分给出WebRowSet对象每行中每列的值。如果已填充priceList对象并且未对其进行任何更改,则 XML 文档的数据元素将如下所示。在下一节中,您将看到在修改priceList对象中的数据时 XML 文档如何更改。

对于每一行,都有一个<currentRow>元素,因为priceList有两列,每个<currentRow>元素包含两个<columnValue>元素。

  1. <data>
  2. <currentRow>
  3. Colombian
  4. 7.99
  5. </currentRow>
  6. <currentRow>
  7. Colombian_Decaf
  8. 8.99
  9. </currentRow>
  10. <currentRow>
  11. Espresso
  12. 9.99
  13. </currentRow>
  14. <currentRow>
  15. French_Roast
  16. 8.99
  17. </currentRow>
  18. <currentRow>
  19. French_Roast_Decaf
  20. 9.99
  21. </currentRow>
  22. </data>

您对WebRowSet对象的更改方式与对CachedRowSet对象的更改方式相同。但是,与CachedRowSet对象不同,WebRowSet对象会跟踪更新,插入和删除,以便writeXml方法可以同时写入当前值和原始值。接下来的三个部分演示了对数据的更改,并显示了每次更改后描述WebRowSet对象的 XML 文档的样子。您不必对 XML 文档做任何事情;对它的任何更改都是自动进行的,就像编写和读取 XML 文档一样。

插入行

如果 Coffee Break 连锁店的所有者想要在价目表中添加新咖啡,则代码可能如下所示:

  1. priceList.absolute(3);
  2. priceList.moveToInsertRow();
  3. priceList.updateString(COF_NAME, "Kona");
  4. priceList.updateFloat(PRICE, 8.99f);
  5. priceList.insertRow();
  6. priceList.moveToCurrentRow();

在参考实现中,紧接在当前行之后进行插入。在前面的代码片段中,当前行是第三行,因此新行将在第三行之后添加并成为新的第四行。为了反映这种插入,XML 文档将在<data>元素中的第三个<currentRow>元素之后添加以下<insertRow>元素。

<insertRow>元素看起来类似于以下内容。

  1. <insertRow>
  2. Kona
  3. 8.99
  4. </insertRow>

删除行

店主决定 Espresso 销售不足,应该从咖啡休息店出售的咖啡中取出。因此,所有者想要从价目表中删除 Espresso。 Espresso 位于priceList对象的第三行,因此以下代码行将其删除:

  1. priceList.absolute(3); priceList.deleteRow();

以下<deleteRow>元素将出现在 XML 文档的数据部分中的第二行之后,表示已删除第三行。

  1. <deleteRow>
  2. Espresso
  3. 9.99
  4. </deleteRow>

修改行

店主进一步决定哥伦比亚咖啡的价格过于昂贵,并希望将其降低至每磅 6.99 美元。以下代码将哥伦比亚咖啡的新价格设定为每磅 6.99 美元,这是第一排的价格:

  1. priceList.first();
  2. priceList.updateFloat(PRICE, 6.99);

XML 文档将在提供新值的<updateRow>元素中反映此更改。第一列的值没有改变,因此只有第二列的<updateValue>元素:

  1. <currentRow>
  2. Colombian
  3. 7.99
  4. <updateRow>6.99</updateRow>
  5. </currentRow>

此时,通过插入行,删除行以及修改行,priceList对象的 XML 文档如下所示:

  1. <data>
  2. <insertRow>
  3. Kona
  4. 8.99
  5. </insertRow>
  6. <currentRow>
  7. Colombian
  8. 7.99
  9. <updateRow>6.99</updateRow>
  10. </currentRow>
  11. <currentRow>
  12. Colombian_Decaf
  13. 8.99
  14. </currentRow>
  15. <deleteRow>
  16. Espresso
  17. 9.99
  18. </deleteRow>
  19. <currentRow>
  20. French_Roast
  21. 8.99
  22. </currentRow>
  23. <currentRow>
  24. French_Roast_Decaf
  25. 9.99
  26. </currentRow>
  27. </data>

WebRowSet 代码示例

示例[WebRowSetSample.java]($docs-gettingstarted.html)演示了此页面上描述的所有功能。