为DB2 XML数据开发Java应用程序
根据关系谓词和 XML 谓词进行过滤
Java 程序也可以指示 DB2 基于适合于 XML 和非 XML 数据的条件来过滤查询输出。下面这个例子构建在前一个例子的基础之上,返回居住在加利福尼亚州圣何塞的 "Silver" 客户的姓名和主电子邮件地址。这个简单的查询从 XML 和非 XML 列检索数据,还基于 XML 和非 XML 列的内容限制数据。
下面这个摘录只包含从前一个例子发生了改变的部分代码。在本例中,SELECT 语句现在调用 XMLExists 作为 WHERE 子句的一部分,以限制居住在指定城市和州(分别在 city 和 state 变量中定义)的客户的结果。
清单 10. 基于 XML 元素值过滤 XML 数据
. . .
String status = "Silver";
String state = "CA";
String city = "San Jose";
. . .
try{
. . . .
String query = "SELECT name, xmlquery('$c/Client/email[1]' " +
" passing contactinfo as \"c\") " +
" from clients where status = ?"
" and xmlexists('$c/Client/Address[state=$state][city=$city]' " +
" passing contactinfo as \"c\", " +
" cast(? as char(2)) as \"state\", " +
" cast(? as varchar(30)) as \"city\" )";
PreparedStatement selectStmt = conn.prepareStatement(query);
selectStmt.setString(1, status);
selectStmt.setString(2, state);
selectStmt.setString(3, city);
. . .
}
该查询的大部分您应该已经熟悉,所以本节只着重介绍它的最后四行。XMLExists 函数指示 DB2 确定一个给定 XML 文档是否包含其中包含特定城市和州的客户地址。PASSING 子句指定可以在哪里找到 XML 文档:在 "contactinfo" 列中。CAST 函数被调用两次,以将输入参数的值(针对城市和州)强制转换适当的数据类型。
该程序的输出类似于 清单 9 展示的输出,假设 Lisa Hansen 和 Amy 都居住在加利福尼亚州圣何塞。
使用 XQuery 作为顶层语言
尽管 DB2 完全支持 XQuery 作为顶层语言,但是最初的 XQuery 规范并不解析参数标志符。作为一个实际问题,这限制了 XQueries 在 Java 应用程序中的使用。前几节演示了如何在 SQL 中嵌入 XQueries(例如,使用 XMLQuery 和 XMLExists 函数),以合并参数标志符。本节介绍利用纯 XQuery 可以在 Java 应用程序中做什么。
下面这个例子中包含的 XQuery 类似于 "Query DB2 XML Data with XQuery"(developerWorks,2006 年 4 月)中给出的。该 XQuery 确定哪些客户居住在加利福尼亚州圣何塞。对于每个这样的客户,它会构造一个包含 "emailList"(其中包含该客户的所有电子邮件地址)的 XML 片段。最后,它返回一个 emailLists 序列。
清单 11. 利用 XQuery 检索 XML 片段
try{
// get a database connection
Connection conn = Conn.getConn();
![]()
// define, prepare, and execute an XQuery (without SQL).
// note that we must hard-code query predicate values.
String query = "xquery for $y in db2-fn:xmlcolumn" +
"('CLIENTS.CONTACTINFO')/Client " +
"where $y/Address/city=\"San Jose\" and $y/Address/state=\"CA\" " +
"return <emailList> { $y/email } </emailList>";
PreparedStatement selectStmt = conn.prepareStatement(query);
ResultSet rs = selectStmt.executeQuery();
![]()
// iterate over all items in the sequence and print results.
while(rs.next() ){
System.out.println(rs.getString(1));
}
![]()
// release all resources
. . .
// catch and handle any exceptions
. . .
}
该查询有两个方面值得注意。首先,查询字符串以关键词 "xquery" 打头。这指示 DB2 使用它的 XQuery 解析器来处理查询。每当使用 XQuery 作为最外层语言时,您都需要这样做。其次,查询以大写形式引用表和列的名称。XQuery 是一种大小写敏感的语言。因为当把该信息写入它的内部编目时,DB2 通常将表和列的名称转换成大写形式,所以 XQuery 必须匹配该信息。
该程序的示例输出如 清单 12 所示。因为为每个符合条件的客户返回一个 "emailList" 项,快速扫视一下该输出,可以看到四个客户符合条件。第一个符合条件的记录包含一个电子邮件地址。第二个不包含(也许是因为客户不提供该信息);因此,它的 emailList 为空。第三个符合条件的记录指出该客户的记录中有两个电子邮件地址。第四个记录包含客户的一个电子邮件地址。
清单 12. 前一个应用程序的示例输出
<emailList><email>newemail@someplace.com</email></emailList>
<emailList/>
<emailList><email>beatlesfan36@hotmail.com</email>
<email>lennonfan36@hotmail.com</email></emailList>
<emailList><email>sailer555@yahoo.com</email></emailList>
您也许感到好奇,为什么并不是每个符合条件的客户的姓名都包含在我们的结果中。答案很简单:XQuery 处理 XML 数据,而客户姓名存储在 SQL VARCHAR 列中。所以,如果您想要输出中包含符合条件的客户的姓名及其电子邮件地址,那么应该编写同时包含 SQL 和 XQuery 的查询。
