使用 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_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
要将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
对象的内容写入流之前填充_对象。在下面的代码行中,方法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 = 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 文档。因为实际的读写是通过writeXml
和readXml
方法的实现在内部完成的,所以作为用户,您不需要了解 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
对象。另外,未列出username
和password
属性,因为它们必须保持 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
列中的值,请使用getString
或updateString
方法,并且驱动程序会像通常那样将其转换为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
演示了此页面上描述的所有功能。