让我们来看看上述代码的详细内容。JDBCSAXParser包括了几个重载的parse()方法。在下表中org.xml.sax.Parser接口需要实现parse(InputSource)与parse(String)方法。其它parse()方法简化了代码并允许通过派生类重载以改变其解析方法。
如果参数为JDBCInputSource类型,Parse(InputSource)方法调用parse(JDBCInputSource)方法,否则,产生一个SAXException事件表示无法处理数据源。 当所提供的信息不足以访问数据库时parse(String)方法产生一个SAXException事件。 Parse(ResultSet,String)方法执行解析的核心逻辑。它遍历结果集中的每一行与字段。在对每一行循环时调用方法StartElement()与endElement()(将数据库表标识作为元素名参数)。同样的,在对每一行记录的每个字段循环时会调用方法StartElement()与endElement()(将行标识作为元素名参数)。在上述两种情况中一个空的属性表作为第二参数传递给startElement()。在访问记录的每个字段时,方法generateSAXEventForColumn()被调用(使用字段名与字段值为参数)。通过对结果集对象使用getString90方法可获得单个字段的值,同样我们需要用一个字符串表征字段数据,并在characters()事件中使用。 方法parse(String, String, String, String)通过传递给它的参数简单有效地建立了一个JDBCInputSource对象,然后可对该对象使用parse(JDBCInputSource)方法。 方法generateSAXEventForColumn()为字段数据产生事件。一个数据库中的字段空值(null)与一个字段零值(empty)有着不同的含义。我们通过过滤那些具有null值的字段来捕获这种差别。另一种表现数据库中null值的方法是使用一个二进制属性(如isNull)。通过该选项,一个真值(true)被认为是null值,否则就不是。 GetTableMarker(),getRowMarker(),及getClumnMarker()方法可分别返回合适的表、行、字段默认值。派生出来的类可重载这些方法以提供特定的标识。 方法GetTableMarker()返回一个“select * from <tableName>”字符串。派生出来的类可通过重载该方法以提供一个不同的select query字符串,并实现数据库级的过滤。 类JDBCSAXUtils提供两种方法来建立一个JDBCInputSource对象:通过属性(property)文件或一个Property对象。它不需要通过SAX或DOM编程接口提供一个有关数据库的参数表给应用程序。它希望用户来提供一个包含完整数据库URL入口的属性文件,一个可连接到数据库的用户名及密码,一个用于建立连接JDBC数据库引擎,及数据库表名。以下是一个典型的属性文件:
我们现在有了一个简单的解析器,它能对数据库表产生适当的SAX事件。它能区分null值并提供一些专用的标识。这些功能对于一些应用已经足够了,而某些完整的解决方案还需要一些附加的功能,这是因为: 解析器不能合并那些关联的信息,该问题的解决可通过使用Xpointer/Xlink来设置表中外键的相关信息。 在数据库中,一个数据库表包含了未排序的字段集;有关字段存储的排序并不重要。另一方面,一个XML DTD,无法描述一个未排序的子元素集。 我们可以通过几种方法处理该问题。如果我们要将数据库转化为另一种XML文档,比如说一个HTML页面,为其定制的XSLT样式表可建立正确排序的输出结果。我们也可以重载getSelectorSQLStatement()方法直接提供一个正确排序的字段列表。 有时我们希望通过某些查询能将一个表的被选择部分作为一个XML文档封装。如果XML工具能实现这样的过滤,我们就可以更好的使用数据库。方法getSelectorSQLStatement()可以通过重载并返回合适的select结果字符串。 解析器通过对结果集(result-set)对象使用getString()方法可获得字符串形式的某个字段值。该操作对于文本、数字等类型的字段非常合适,但对于二进制数据就不适合。当使用文本表示二进制数据时,在某些操作中会无法使用。解析器同样无法处理某些可被SQL3/JDBC2.0接受的用户自定义的数据类型。 对于上述问题我们可以通过重载generateSAXEventForCloumn()方法以及提供一种合适的处理(implementation)来实现。 面向数据库的DOM编程接口实现
有关类JDBCDOMParser的实现较为简单,它通过JAXP所提供的XmlDocumentBuilder类可以从一个SAX事件流构建一个DOM文档。JDBCDOMParser仅有一个方法:createDocument(),它需要一个JDBC数据源作为参数。该方法建立一个JDBCSAXParser并可用其来解析一个实际的XmlDocumentBuilder对象。然后它释放解析对象并返回XmlDocumentBuilder对象中产生的结果。在实际编程实现中,XmlDocumentBuilder对象通过建立一个DOM文档的方法来响应JDBCSAXParser对象所产生的SAX事件。 · 利用面向数据库的SAX编程接口 我们已经看了一个通过面向数据库的SAX编程接口来实现DOM编程接口的实例。现在我们要看另一个使用SAX编程接口的例子。在本节中,我们将看到如何将SAX数据库编程接口与XT(一个用Java写的XSLT处理器)相集成。通过这种集成,我们可以对一个存储在数据库中的虚拟XML文档直接使用XSLT样式表。 我们封装了实际建立一个SAX数据库源的逻辑,并用给定的XSLT样式表加以处理,在类JDBCXSLProcessor中产生一个输出文件(使用XT中的com.jclark.xsl.sax.Driver)。其中主要的方法包含三个参数:一个数据库特征文件,一个XSLT样式表文件,一个输出文件。 (要查看有关JDBCXSLProcessor.java的代码, 请点击此处.) (要查看关于createTable.xsl的源代码, 请点击此处.)
注意虽然一个XSLT样式表可以容易地实现数据的成批转换,不过这种方法并不十分有效,因为一个完整的样式表其逻辑也许会非常复杂,从而影响样式表的建立及实际数据转换的效率。尤其当数据库表中包含大量记录时这个问题会特别明显。一个折衷的方法是写一个专门用于批量转换的应用程序。这样一个应用程序可以监听SAX事件并建立XML元素(及对应的实际数据),所产生的结果XML文档与数据库表相对应。 · 使用DOM数据库编程接口 在大多数场合,SAX数据库编程接口较DOM编程接口更节约系统资源。不过,某些应用程序要求随意的访问XML文档,因此就会需要提供一个类似与DOM的树形结构来表示数据库。 · 将DOM数据库编程接口与XQL处理器相集成 XML Query Language(XQL)是一种用于XML文档查找的语言,其语法与Xpath方式相近。在这里,我们将我们的DOM数据库解析器与GMD-IPSI'S XQL Engine相集成。通过这种集成我们可以对一个表征数据库表的XML文档执行类似于SQL的查询。 作为一个集成的例子,作者提供一个简单封装的用于查询一个基于数据库表的XML文档。类JDBCXQLProcessor建立一个类似于封装的环境,它接收客户的查询并输出结果文档。方法PprocessQueries()可以操作任何文档对象??不仅是由JDBCDOMParser所建立的对象。它读系统,执行查询请求并输出系统的查询结果。Main()方法可通过其参数建立一个JDBCInputSource对象并将其传递给JDBCDOMParser以获得一个与所给数据库表相对应的文档对象。 (要查看JDBCXQLProcessor的Java代码,请点击此处.) · 结论 在本文中,我们讨论了如何通过面向数据库的XML编程接口来表征数据库中的信息。通过这种编程接口,我们可以避免将一个数据库转换为一个实际的XML文档以及避免保持二者间的同步。我们介绍了一种通过Java实现的SAX与DOM数据库编程接口,然后介绍了一种与XT相集成的SAX编程接口。我们演示了通过这种集成由数据库表直接导出HTML页面以及将数据库表转换为XML文档。最后,我们将DOM数据库编程接口与一个XQL处理器相集成。 · 关于作者 Ramnivas Laddad 是一个Java的SUN认证工程师。他有一个电子工程通讯技术专业的硕士学位,有六年的软件开发经验(关于网络,图形用户界面,分布式系统等等)。在面向对象的软件系统方面有丰富经验(五年C++,两年Java)。Ramnivas现在http://www.rti.com/工作,致力于设计与研究ControlShell(一种用于复杂实时监控系统的模块化编程框架技术)。 |