使用 WebRowSet 对象

WebRowSet对象非常特殊,因为除了提供CachedRowSet对象的所有功能之外,它还可以将自己写为 XML 文档,还可以读取该 XML 文档以将自身转换回WebRowSet对象。由于 XML 是不同企业之间可以通过其进行通信的语言,因此它已成为 Web 服务通信的标准。结果,通过使 Web 服务能够以 XML 文档的形式从数据库发送和接收数据来满足WebRowSet对象的需求。

涵盖以下主题:

Coffee Break 公司已扩展为在线销售咖啡。用户从 Coffee Break 网站按磅 Order 咖啡。通过从公司数据库获取最新信息,可以定期更新价格表。本节演示如何使用WebRowSet对象和单个方法调用将价格数据作为 XML 文档发送。

创建和填充 WebRowSet 对象

使用参考实现WebRowSetImpl中定义的默认构造函数创建一个新的WebRowSet对象,如以下代码行所示:

WebRowSet priceList = new WebRowSetImpl();

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

您可以使用从RowSetProvider类创建的RowSetFactory实例来创建WebRowSet对象。有关更多信息,请参见使用 JdbcRowSet 对象中的使用 RowSetFactory interface

Coffee Break 总部定期将价格表更新发送到其网站。 WebRowSet对象上的此信息将显示一种在 XML 文档中发送最新价格清单的方式。

价格表由表COFFEES中的COF_NAMEPRICE列中的数据组成。以下代码片段设置所需的属性,并使用价目表数据填充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_NAMEPRICE列中的数据,以及有关这两列的元数据。

将 WebRowSet 对象写入和读取为 XML

要将WebRowSet对象写为 XML 文档,请调用writeXml方法。要将 XML 文档的内容读入WebRowSet对象,请调用readXml方法。这两种方法都在后台运行,这意味着除结果外,其他所有内容对于您都是不可见的。

使用 writeXml 方法

方法writeXml将调用它的WebRowSet对象写为表示其当前状态的 XML 文档。它将此 XML 文档写入传递给它的流中。流可以是OutputStream对象(例如FileOutputStream对象)或Writer对象(例如FileWriter对象)。如果传递方法writeXmlOutputStream对象,则将以字节为单位写入,该字节可以处理所有类型的数据。如果将其传递给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对象的内容写入流之前填充_对象。在下面的代码行中,方法writeXmlResultSet对象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 = new
    java.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);

XML 文档中的内容

RowSet个对象不仅仅是它们包含的数据。它们还具有有关其列的属性和元数据。因此,表示WebRowSet对象的 XML 文档除其数据外还包括其他信息。此外,XML 文档中的数据包括当前值和原始值。 (回想一下,原始值是在对数据进行最新更改之前立即存在的值.这些值对于检查数据库中的相应值是否已更改是必需的,从而在应持久化该值上造成冲突:您在RowSet对象中 Importing 的新值或其他人在数据库中 Importing 的新值.)

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

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

元素标签表示元素的开始和结束。例如,<properties>标记表示属性元素的开始,而</properties>标记表示其结束。 <map/>标签是表示 Map 子元素(属性元素中的子元素之一)尚未分配值的简写方式。以下示例 XML 文档使用空格和缩进使其更易于阅读,但在实际的 XML 文档中并没有使用,其中空格并不代表任何意义。

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

Properties

priceList对象上调用方法writeXml将产生描述priceList的 XML 文档。该 XML 文档的 properties 部分如下所示:

<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>
    <column>1</column>
  </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对象。另外,未列出usernamepassword属性,因为它们必须保持 Secret。

Metadata

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

<metadata>
  <column-count>2</column-count>
  <column-definition>
    <column-index>1</column-index>
    <auto-increment>false</auto-increment>
    <case-sensitive>false</case-sensitive>
    <currency>false</currency>
    <nullable>0</nullable>
    <signed>false</signed>
    <searchable>true</searchable>
    <column-display-size>
      32
    </column-display-size>
    <column-label>COF_NAME</column-label>
    <column-name>COF_NAME</column-name>
    <schema-name></schema-name>
    <column-precision>32</column-precision>
    <column-scale>0</column-scale>
    <table-name>coffees</table-name>
    <catalog-name>testdb</catalog-name>
    <column-type>12</column-type>
    <column-type-name>
      VARCHAR
    </column-type-name>
  </column-definition>
  <column-definition>
    <column-index>2</column-index>
    <auto-increment>false</auto-increment>
    <case-sensitive>true</case-sensitive>
    <currency>false</currency>
    <nullable>0</nullable>
    <signed>true</signed>
    <searchable>true</searchable>
    <column-display-size>
      12
    </column-display-size>
    <column-label>PRICE</column-label>
    <column-name>PRICE</column-name>
    <schema-name></schema-name>
    <column-precision>10</column-precision>
    <column-scale>2</column-scale>
    <table-name>coffees</table-name>
    <catalog-name>testdb</catalog-name>
    <column-type>3</column-type>
    <column-type-name>
      DECIMAL
    </column-type-name>
  </column-definition>
</metadata>

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

Data

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

每行都有一个<currentRow>元素,并且由于priceList有两列,因此每个<currentRow>元素都包含两个<columnValue>元素。

<data>
  <currentRow>
    <columnValue>Colombian</columnValue>
    <columnValue>7.99</columnValue>
  </currentRow>
  <currentRow>
    <columnValue>
      Colombian_Decaf
    </columnValue>
    <columnValue>8.99</columnValue>
  </currentRow>
  <currentRow>
    <columnValue>Espresso</columnValue>
    <columnValue>9.99</columnValue>
  </currentRow>
  <currentRow>
    <columnValue>French_Roast</columnValue>
    <columnValue>8.99</columnValue>
  </currentRow>
  <currentRow>
    <columnValue>French_Roast_Decaf</columnValue>
    <columnValue>9.99</columnValue>
  </currentRow>
</data>

更改 WebRowSet 对象

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

Inserting Rows

如果 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>
  <columnValue>Kona</columnValue>
  <columnValue>8.99</columnValue>
</insertRow>

Deleting Rows

所有者认为 Espresso 的销量不足,应将其从 The Coffee BreakStore 出售的咖啡中删除。因此,所有者希望从价格表中删除 Espresso。 Espresso 位于priceList对象的第三行,因此以下代码行将其删除:

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

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

<deleteRow>
  <columnValue>Espresso</columnValue>
  <columnValue>9.99</columnValue>
</deleteRow>

Modifying Rows

店主进一步认为哥伦比亚咖啡的价格太贵了,希望将其降至每磅 6.99 美元。以下代码将第一行中的哥伦比亚咖啡的新价格设置为每磅 6.99 美元:

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

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

<currentRow>
  <columnValue>Colombian</columnValue>
  <columnValue>7.99</columnValue>
  <updateRow>6.99</updateRow>
</currentRow>

此时,插入一行,删除一行并修改一行,用于priceList对象的 XML 文档将如下所示:

<data>
  <insertRow>
    <columnValue>Kona</columnValue>
    <columnValue>8.99</columnValue>
  </insertRow>
  <currentRow>
    <columnValue>Colombian</columnValue>
    <columnValue>7.99</columnValue>
    <updateRow>6.99</updateRow>
  </currentRow>
  <currentRow>
    <columnValue>
      Colombian_Decaf
    </columnValue>
    <columnValue>8.99</columnValue>
  </currentRow>
  <deleteRow>
    <columnValue>Espresso</columnValue>
    <columnValue>9.99</columnValue>
  </deleteRow>
  <currentRow>
    <columnValue>French_Roast</columnValue>
    <columnValue>8.99</columnValue>
  </currentRow>
  <currentRow>
    <columnValue>
      French_Roast_Decaf
    </columnValue>
    <columnValue>9.99</columnValue>
  </currentRow>
</data>

WebRowSet 代码示例

samplesWebRowSetSample.java演示了此页面上描述的所有功能。