摘要 过去几年XML技术作为Internet上交换信息的格式受到了极大的欢迎。今天XML常常被描述成一种孤立的技术,但它最初诞生的时候却是一种(介于HTML和SGML之间的)Internet技术。本文讨论XML如何被用作数据库和最终用户间的“通讯协议”。
当前最流行的关系数据库管理系统用SQL查询语言来与数据打交道。虽然面向XML(XML-oriented)的数据库已经面市,却不常见。而XML如此流行,关系数据库开发者也在为产品增加XML兼容性的过程中学习进步。本文考察其中一种途径:让数据库返回XML。示范代码中用到了一个Oracle数据库,它被假定是XML兼容的,能处理XML数据。
本文分为两部分。第一部分预备和Oracle数据库打交道的Java代码:提交一个SQL查询,获取一个XML输出;第二部分专注于一个web程序:将从数据库获取的XML数据输出为HTML文本。
要求 本文中用到下列软件:
BEA WebLogic Platform 8.1 with SP4 ——作应用程序服务器。
Oracle 10g Database Server ——作数据库服务器。你可以用不同版本的服务器来试验代码;据我们所知,本方案不需要特定的版本。
Oracle XML-SQL Utility (XSU) ——XSU是一组充当PL/SQL包装(wrapper)的Java类,它允许查询返回XML包装起来的结果集或对象。
Oracle XML Parser, Version 2 ——Oracle的基于Java校验XML有效性的解析器(parser),支持XSL。一般来讲XSU和XML解析器是Oracle Developer Suite的一部分。
本文中的代码在微软Windows XP系统上运行,但只需要很小的改动也应该能在任何操作系统上正确工作。
我们假定读者是有经验的Java开发者,熟悉BEA WebLogic Server,并且有JDBC编程经验。
准备连接池(Connection Pool)和数据源 如果你熟悉JDBC连接池和数据源的配置,请跳过这一节。
首先需要配置连接池和数据源。代码稍后会用JNDI来获取数据源,这需要一点配置。我们要配置一个JDBC连接池来保持和数据库的连接。登入WebLogic的控制台并选择Service Configurations -> JDBC -> Connection Pools节点。
现在选择“Configure a new JDBC Connection Pool...”以创建一个新的连接池,在接下来的画面里选择数据库类型和驱动(图1)。
图1. JDBC连接池:选择数据库 可以看到多种不同数据库可供选择。我们需要的数据库类型(Database Type)是Oracle,并且将使用BEA的Oracle Driver(Type 4)。然后点“Continue”按钮定义连接属性(图2)。
图2. JDBC连接池:连接属性 在这个画面中,为JDBC连接池选择一个名字,并设置其它诸如数据库名和主机名、连接端口和口令等数据库参数。
这里并不创建一个新数据库和一组表,我们将使用Oracle的示例SCOTT/TIGER模式(schema)和EMP表。几乎每个Oracle安装中都有这个示例,因此不需要你再去配置。如果没有EMP表或者这个表是空的,可以用Oracle目录下的\sqlplus\demo\demobld.sql脚本重建这个表并装入数据,还可以用\sqlplus\demo\demodrop.sql删除原有的值。
配置好这些参数之后点“Continue”(图3)。
图3. JDBC连接池:连接测试 一般情况不必对这一页做任何改动,这是一个连接测试页(可以点“Skip This Step”跳过)。WebLogic Server显示了驱动类名、(JDBC驱动使用的)URL和身份验证(用户名和密码)以供核对。复核完这些参数后准备测试,点“Test Driver Configuration”按钮,如果一切正确,将看到“Connection Successful”的信息。最后点“Create and deploy”按钮完成JDBC连接池配置。
完成了JDBC连接池的工作,现在我们需要创建相应的数据源。回到WebLogic Server控制台的主页,按照这个顺序选择:Service Configurations -> JDBC -> Data Source。在接下来的画面中点击“Configure a new JDBC Data Source”链接,将看到数据源配置成功页(图4)。
图4. 数据源配置成功页 要定义JDBC数据源名称和能找到数据源的地方——JNDI路径。务必记住JNDI路径,稍后将用它来建立一个与我们代码的连接。接下来选择“Continue”,然后选择正确的连接池和数据源关联。选中刚刚创建的连接池,再点“Continue”,下一页允许你选择部署数据源的服务器和簇。从列表里选中需要的一个,接着点“Create”。数据源已经创建好,我们准备写代码了。
准备独立(Stand-Alone)Java程序的环境 让我们給即将编写的小客户程序准备一个环境。为了能执行SQL查询和获取XML数据作为输出,将用到Oracle XML-SQL utility (XSU),需要配置环境变量CLASSPATH指向Oracle XML-SQL Utility的库(library)和Oracle XML解析器。一般情况下XSU可以在Oracle的目录\rdbms\jlib\xsu12.jar找到,XML 解析器在\lib\xmlparserv2.jar。还有我们在使用JNDI,需要在CLASSPATH中包括weblogic.jar文件,一般在WebLogic Server的安装目录下:\bea\weblogic81\server\lib\weblogic.jar。
典型的CLASSPATH 看起来会像下面这样:
CLASSPATH=c:\Program Files\java\jdk1.5.0_01\lib;.;
C:\DevSuiteHome\rdbms\jlib\xsu12.jar;
C:\DevSuiteHome\lib\xmlparserv2.jar;
C:\bea\weblogic81\server\lib\weblogic.jar;
考察独立Java程序的代码 在展示代码前,注意到Oracle中有两种处理XML的方法是有意义的。二者的区别很大,你应该采用适合你手头任务的办法。第一种办法是用Oracle的XSU,允许从任何SQL查询返回XML;第二种办法是用Oracle的XMLType列类型(column type)。
XMLType列允许将XML当做数据库中的一种本地数据类型。因此,这些列可以像其它类型的列一样参与查询Consequently。Oracle提供了XMLTYPE()函数来创建一个XMLType数据对象,同时还提供了其它处理这个数据类型的函数,比如XMLELEMENT()和XMLAGG()。从WebLogic Server的在线文档(The Oracle Driver)或技术网站(Oracle Technology Network)可以读到关于这种办法的说明和示例。本文将专注于使用XSU的方法。
下面是在Oracle数据库上执行SQL查询并产生XML输出所需要的全部代码(oraxml.java)。
1. import javax.naming.*;
2. import javax.sql.*;
3. import java.sql.*;
4. import oracle.xml.sql.query.*;
5. public class oraxml
6. {
7. public static void main(String args[]) throws SQLException, NamingException
8. {
9. String tabName = "emp";
10. int maxRows = 3;
11. Context ctx = new InitialContext ();
12. DataSource ds = (DataSource) ctx.lookup ("MyOra");
13. Connection conn = ds.getConnection ();
14. OracleXMLQuery qu = new OracleXMLQuery ( conn, "select EMPNO, ENAME from " + tabName);
15. qu.setMaxRows (maxRows);
16. qu.setRowsetTag ("EMPLOYERS");
17. qu.setRowTag ("PERSON");
18. String xmlString = qu.getXMLString();
19. System.out.println (xmlString);
20. conn.close ();
21. }
22. }
这段代码很简单。11-12行获取一个JNDI名称为MyOra的数据源;13和20行分别建立和关闭连接;最有意思的是14-18行执行了一个所谓的“XML查询”;从技术上讲,这是一个经XSU转换为XML的SQL查询;14行初始化查询;15-17行设置XML文档的结构,15行设定返回的最大行数不超过maxRows,16和17行设定文档的根元素(root element)和项目分隔符(item delimiters);18行生成一个XML文档并将其放在xmlString变量中。就像你看到的这样,代码很简单易懂。(英文编者注:注意,这不是成品代码。最后应该在一个finally语句的括号中关闭连接。)
别忘记这段代码中用到了JNDI。作为一个独立的Java程序,必须安排一个命名提供者(naming provider)給它使用。我们将用WebLogic Server作为提供者,配置方法首先要建一个jndi.properties文件,然后确保可以从环境变量访问这个文件。如果CLASSPATH包含当前目录(.),就应该将jndi.properties文件放在当前目录中。这是一个jndi.properties 文件的内容:
java.naming.factory.initial=weblogic.jndi.WLInitialContextFactoryjava.naming.provider.url=t3://localhost:7001
典型的编译命令和运行结果像下面所展示的这样(注意输出被限制为不大于maxRows):
C:\white\work\Java\xmlweb_src>javac oraxml.javaC:\white\work\Java\xmlweb_src>java oraxml<?xml version = '1.0'?><EMPLOYERS> <PERSON num="1"> <EMPNO>7369</EMPNO> <ENAME>SMITH</ENAME> </PERSON> <PERSON num="2"> <EMPNO>7499</EMPNO> <ENAME>ALLEN</ENAME> </PERSON> <PERSON n