`
zhangziyangup
  • 浏览: 1076211 次
文章分类
社区版块
存档分类
最新评论

DB2 XML 编程,第 1 部分: 理解 XML 数据模型

 
阅读更多

简介

正如 W3C 推荐标准 所指出的,XML 的一些设计目标是针对语言的应用程序开发方面:

  • “XML 将会支持各种各样的应用程序。”
  • “编写处理 XML 文档的程将会很容易。”

其他目标(比如可读性、序列化和传输)得到了许多关注,但是应用程序开发目标没有得到同样的关注。

本文是本系列的第一篇,本系列从三个层面讨论 XML 对应用程序开发的影响:

  • 第 1 部分讨论在哪些情况下在应用程序开发中使用 XML 可以使应用程序开发过程更简单、成本更低、更可移植和质量更高。在这十年中,XML 编程将使应用程序开发方式发生根本性变化,这种变化甚至可能与面向对象方法在过去十年中的影响相当。
  • 第 2 部分主要讨论数据库的角色。重点是 DB2 9(原来的代码号是 Viper)和 Viper 2 功能。将了解:
    • 新的 XML 存储和查询环境如何操作应用程序层的 XML 数据模型
    • 采用新的基于 XML 的应用程序开发体系结构之后,数据库模式如何变得更简单更自然
    • 如何按照在应用程序中查询数据的相同方式查询数据库中的 XML 数据
    • 最后,如何结合关系数据和 XML 数据,从而同时获得这两个环境的优势。
  • 第 3 部分主要关注客户机,介绍在 Web 浏览器和 Web 服务器中使用的 XML 技术:Ajax、XSLT、SVG、Comet、feed 和 mashup。学习如何在数据库中生成 feed 和 Web 服务,在应用程序层查询和组合它们,然后在客户机浏览器中显示它们。
  • 第四篇文章将所有这些技术结合在一起,并展示一个真实的示例。

XML 数据模型基本知识

在传统上,XML 用来定义业务文档的元数据。Document Object Model(DOM)用来在应用程序中操作这些元数据。如果我们查看 DOM,就会看到它为层次化 XML 数据结构提供一个对象接口,可以用 DOM API 操作这个层次结构。换句话说,DOM 可以作为对象包装器操作任何可以用 XML 表示的数据结构。

在 XML 数据模型中,将许多应用程序数据对象定义为 XML。因为 XML 是层次化的,所以很容易以自然的、人可读的格式捕捉不同数据对象之间的关系。

注意:
如果数据已经是 XML 格式的,过程的其余部分就很自然很简单了。如果数据是关系格式,仍然可以使用这种方法,但是需要在关系数据和 XML 数据之间建立双向映射。这个步骤可以使用 SQL/XML 发布和分解函数来实现。大多数关系数据库支持这些函数和其他映射技术。对于在应用程序开发中只使用 XML 作为数据模型的许多开发人员,关系数据到层次化数据(XML)的映射似乎是不必要的。但是作为开发人员,在将关系映射到数据对象时,我们总是这么做。使用 XML 数据模型的优点可能足以促使许多开发人员考虑在应用程序开发中使用 XML,即使在他们的业务模型中并不需要 XML 数据。

定义了 XML 数据模型之后,可以使用 DOM 解析器在应用程序中实例化 XML 数据模型。为了隔离应用程序代码与用来导航和操作 XML 模型的 DOM API,可以为 DOM 和 XPath 实现创建一个包装器。这个包装器也会使应用程序代码的可移植性更好。

本文提供了 一个 Java 包装器示例,您可以直接使用它,也可以用它作为模板建立自己的包装器。应用程序的业务逻辑使用包装器 API 直接操作 XML 模型。修改后的 XML 数据可以轻松地序列化,并在不同对象或多层环境(SOA)的不同层之间传递。

XML 数据模型与数据对象模型

大多数应用程序由业务对象组成,业务对象操作数据对象的层次结构。数据对象一般是业务数据的简单包装器。它们的主要用途是以受控制的方式向业务对象公开封装的数据。使用对象包装器的另一个好处是,它们可以以自然的对象层次结构表达关系表中存储的数据,从而捕捉数据之间的关系。编程工作的一个主要部分就是为应用程序业务数据创建这些对象包装器。

因为 XML 本质上维护数据结构之间的关系,所以不需要创建单独的对象层次结构来捕捉各个数据结构之间的关系。另外,XML 已经有一个标准的对象模型,Document Object Model(DOM)。这个模型的实现处理 XML 数据的构造、修改和序列化。通过结合使用 XPath 和 DOM API,很容易在业务应用程序中装载、修改和保存 XML 数据。

一个真实示例

为了更好地理解这两个模型之间的差异,我们来看看每个模型如何影响应用程序的设计和实现。

我将使用一个简单的场景演示这两种方式,这个场景要处理客户和订单信息。

数据对象模型

按照数据对象模型方式,首先需要创建包装器对象来封装客户和订单数据,见清单 1、清单 2 和清单 3。


清单 1. 创建客户

publicclassCustomer
...{
intcustomerid;
Stringfirstname;
Stringlastname;
Itemsitemspurchased;

PublicCustomer(
intcustid,Connectionconn)
...{
Statementdbstmt
=conn.createStatement();
ResultSetdbResult
=dbstmt.executeQuery("selectfname,lnamefrom
customer_tablewherecustomerid=custid");
customerid=custid;
SetFirstName(dbResult.getString(
1));
SetLastName(dbResult.getString(
2));
}

publicStringGetFirstName...{returnfirstname;}
publicVoidSetFirstName(fname)...{firstname=fname;}
publicStringGetLastName...{returnlastname;}
publicVoidSetLastName(lname)...{lastname=lname;}
publicItemsGetItemsList...{returnitemspurchased;}
publicSetItemsList(list)...{itemspurchased=list;}
}

清单 2. 创建 Items 类

publicclassItems
...{
Hashtablelist
=newHashtable();

PublicItems(
intcustid,Connectionconn)
...{
Statementdbstmt
=conn.createStatement();
ResultSetdbResult
=dbstmt.executeQuery("selectitemid,description,
price,datefrompurchase_tablewherecustomerid=custid")
While(dbResult.rs.next())
...{
tempitem
=newItem();
tempitem.SetID(dbResult.getString(
1));
tempitem.SetDescription(dbResult.getString(
2));
tempitem.Setprice(dbResult.getFloat(
3));
tempitem.SetpurchaseDate(dbResult.getString(
4));
Additem(tempitem);
}

}


publicvoidAddItem(itemoneitem)...{list.put(oneitem.GetID(),oneitem);}
publicItemGetItem(ItemID)...{returnlist.get(StringitemID);}
publicHashtableGetItems()...{returnlist;}
publicItemsFindItemByPrice(flaotmin,floatmax)
...{
ItemsretList
=newItems();
for(Enumeratione=list.elements();e.hasMoreElements();)
...{
itemtmpItem
=(item)e.nextElement();
floatprice=tmpItem.GetPrice();
if(price>=min&&price<=max)
...{
retList.AddItem(tmpItem);
}

}

}

publicItemsFindItemByDate(purchaseDate)...{}
}

清单 3. 创建 Item 定义

publicclassItem
...{
Stringid;
Stringdescription;
StringpurchaseDate;
Floatprice;

Public
voidSetID(StringItemID)...{id=ItemID;}
Public
voidSetDescription(Stringdesc)...{description=desc;}
Public
voidSetpurchaseDate(StringpDate)...{purchaseDate=pDate;}
Public
voidSetprice(floatpprice...{price=pprice;}
PublicStringGetID()
...{returnid;}
PublicStringGetDescription()
...{returndescription;}
Public
floatGetPrice()...{returnprice;}
}

现在可以在应用程序中使用这些数据对象来管理底层数据。


清单 4. 在应用程序中操作数据对象

Customercustomer=newCustomer(custid,dbConnection)
customer.SetItemList(
newItems(custid,dbConnection));
Itemslist
=customer.GetItemsList().FindItemByPrice(15.0,25.50);
for(Enumeratione=list.elements();e.hasMoreElements();)
...{
System.out.println(((item)e.nextElement()).GetDescription());
}

在上面的示例中,我们发现数据对象的代码比业务逻辑需要的代码多得多。另外,因为包装器对象隐藏了底层业务数据之间的关系,所以包装器对象 API 必须有良好的文档记录,应用程序开发人员才能了解如何正确地使用它们。

在数据对象模型中,很容易在对象层次结构之间进行简单的导航,但是必须为每个搜索条件实现高级搜索和导航功能(例如 FindItemByPrice)。

XML 数据模型

因为包装器的主要用途是封装业务数据,所以可以用 XML 数据模型替换它们。


清单 5. XML 数据模型

<Customercustomerid=""firstname=""lastname="">
<Items>
<ItemID=""description=""purchaseDate=""price=""/>
</Items>
</Customer>

现在,假设数据库中的数据已经存储为 XML 格式:

  • 客户数据存储为 <Customer customerid ="" firstname="" lastname="" />
  • 商品数据存储为 <Item ID="" description="" purchaseDate="" price="" />

那么,对于任何给定的客户,我们只需获取客户 XML 并在其中插入查询的商品列表。

重写应用程序代码,让它使用 XML 模型保存客户和商品信息。为了创建和操作这个 XML 数据模型的实例,我们将使用 DOM 包装器类 XMLParse(见 下载 一节)。

第一种情况 —— 数据在数据库中存储为 XML 格式


清单 6. 重写应用程序来使用 XML 模型
1.Statementdbstmt=conn.createStatement();
2.ResultSetdbResult=dbstmt.executeQuery("selectcustXMLfrom
customer_tablewherecustomerid=custid");

3.XMLParsecustomerXML=newXMLParse(dbResult.getString(1));
4.customerXML.appendNode("/Customer",customerXML.createNode("<Items/>"))

5.dbResult=dbstmt.executeQuery("selectitemXMLfrompurchase_table
wherecustomerid=custid");
6.While(dbResult.rs.next())...{
7.Nodeitemnode=customerXML.createNode(dbResult.getString(1));
8.customerXML.appendNode(itemnode,"/Customer/Items",false);
}

9.customerXML.find("/Customer/Items/item[@price>15.0and@price<25.5]",true);
10.for(inti=0;i<customerXML.currentFind.getLength();i++)...{
11.System.out.println(customerXML.getValue("@description",i));
}

第一个查询(第 2 行)返回给定客户的 custXML 列中的 XML 数据。将这个 XML 字符串传递给 DOM 包装器的构造器(第 3 行),DOM 包装器进而使用 XML 解析器实例化一个代表 XML 数据的对象层次结构。

注意:因为客户 XML 中还没有任何 Items 元素(这符合我们在模型中定义的 XML 模式),所以我们创建一个新的 Items 元素(第 4 行),并把它作为子元素追加到 Customer 元素中。

第二个查询(第 5 行)从数据库中获取这位客户购买的商品的列表。将列表中的每个商品(第 7 行)追加到 DOM 对象层次结构中 Customer/items 路径的下面(第 8 行)。

最后,使用 XPath 在 DOM 对象层次结构中搜索给定价格范围内的所有商品(第 9 行),并输出搜索到的每个商品的说明(第 10 行)。

第二种情况 —— 所有数据在数据库中存储为关系形式

因为数据没有存储为 XML 格式,所以需要在查询中使用 SQL/XML 发布函数执行转换。


清单 7. 使用 SQL/XML 发布函数执行转换

1.Statementdbstmt=conn.createStatement();
2.ResultSetdbResult=dbstmt.executeQuery("selectxmlelement(name"Customer",
xmlattributes(customeridas"customerid"),
xmlattributes(fnameas"firstname"),
xmlattributes(lnameas"lastname")
)fromcustomer_tablewherecustomerid=custid");

3.XMLParsecustomerXML=newXMLParse(dbResult.getString(1));

5.dbResult=dbstmt.executeQuery("selectxmlelement(name"items",
xmlelement(name"item",
xmlattributes(itemidas"id"),
xmlattributes(descriptionas"description"),
xmlattributes(priceas"price"),
xmlattributes(dateas"purchaseDate")
)
)frompurchase_tablewherecustomerid
=custid");
6.if(dbResult.rs.next())...{
7.Nodeitemsnode=customerXML.createNode(dbResult.getString(1));
8.customerXML.appendNode(itemsnode,"/Customer",false);
}


9.customerXML.find("/Customer/Items/item[@price>15.0and@price<25.5]",true);
10.for(inti=0;i<customerXML.currentFind.getLength();i++)...{
11.System.out.println(customerXML.getValue("@description",i));
}

所以,即使数据库中没有 XML,仍然可以用 SQL 创建关系数据的 XML 视图。另外,在查询中生成商品 XML 的同时,我们添加了外层的 Items 元素。现在,只需将商品 XML 添加到客户 XML 中。应用程序的其余部分是相同的。

与纯对象模型相比使用 XML 模型的好处

数据对象包装器在应用程序代码中占很大的比例,这会大大分散开发人员对管理数据对象的业务逻辑的注意力。另外,这些多余的代码会导致:

  • 额外的成本
  • 更多的 bug
  • 更长的应用程序开发周期
  • 难以移植的代码
  • 当数据模式中发生任何修改时,需要修改或重新生成对象层次结构
  • 代码更难维护
  • 没有内置的数据检验功能
  • 需要有更多的文档来解释包装器对象
  • 对于对象层次结构中的高级搜索和导航等功能,需要相当复杂的逻辑实现
  • 由每个业务对象处理数据序列化
  • 如果使用工具进行映射,应用程序就被限制在这种工具上,难以更换工具

通过使用 XML 编程方法,就可以取消整个包装器对象层次结构,让开发人员将注意力集中在业务逻辑上,而不会为业务数据结构分心。XML 可以给应用程序开发带来以下好处:

  • 减少代码,从而提高质量、降低成本并提高灵活性。
  • 促进 RAD 开发。
  • XPath 解析器已经内置了高级搜索和导航功能。
  • XML 模型内置了约束检查和模式检验功能。
  • 模型内置了持久化功能。任何时候都可以把 XML 数据层次结构存储到文件、字符串或流中。
  • 不需要额外的工具。
  • 这种方法向业务逻辑公开了关系和数据层次结构。在业务对象代码中,很难了解要操作的业务数据结构的格式(也就是,对业务代码隐藏了数据模型)。在关系环境中,这是必要的;但是在 XML 环境中,这可能是一个缺点。
  • 业务逻辑代码容易理解,因为 XPath 描述了数据的性质以及数据与业务结构的关系。

采用 XML 模型时所涉及的问题和解决方案

如果关系数据没有存储为 XML 格式,就必须把它们映射到 XML。尽管大多数关系数据库厂商都提供了相关工具,但是映射过程非常繁琐。但是,由于 DB2 和 Microsoft® SQL Server 等数据库服务器引入了纯 XML 功能,将 XML 数据分解并映射到关系表不再是必需的。通过使用 XQuery 和 XML 索引,现在可以在应用程序中按原样搜索和获取存储的 XML 数据,采用的方式与从数据库获取大字符对象相同。

对于在数据库中存储为纯 XML 的数据,需要了解如何用 SQL/XML 函数和 XQuery 执行查询。应该先学习简单的 XPath 搜索,然后使用复杂的 XQuery,这样比较容易掌握 XML 查询。

了解并精通 DOM API 及其实现,以及掌握如何使用 XPath 导航和搜索 XML 层次结构,可能有点儿难度。可以使用 本文附带的 helper 类 减少对 DOM API 的直接调用。这个 helper 类封装了 DOM API 并公开更自然的 API,可以从应用程序代码调用这些 API。它提供了实例化和序列化 XML 模型以及在 XML 实例中搜索和修改数据或元数据所需的所有功能。包装器类还在必要时处理 XSL 转换、名称空间和模式检验。

在应用程序的业务逻辑中直接嵌入 DOM API 是一种低效率的做法,因为对 XML 模式的任何修改都要求对应用程序代码做大量修改。使用许多 API 调用在层次结构中导航;这会降低代码的可读性。导航或修改的数据对象不如使用用户定义的对象包装器时那么明显。包装器类避免了在业务逻辑中嵌入 DOM API 调用。因为这个包装器类使用 XPath 导航 DOM,所以如果对模式的任何修改影响到应用程序代码,那么只需修改应用程序中受影响的包装器 API 调用中的 XPath 字符串。另外,因为 XPath 指出了要操作的 XML 节点在层次结构中的位置,所以应用程序代码的可读性非常高。

结束语

业务应用程序主要关注创建、操作、存储和表示业务数据。为业务数据建立数据对象包装器是为了让业务逻辑更容易处理业务数据。但是,创建和维护这些数据对象包装器的成本很高,会使开发人员过分关注数据处理逻辑,而分散了对业务逻辑的注意力。

通过使用 XML 数据模型,就可以取消整个数据对象包装器层次结构,让开发人员将注意力集中在业务逻辑上,而不会为业务数据管理分心。通过使用 DOM 包装器类,应用程序代码可以与 DOM API 隔离开。使用 XPath 进行导航可以明确指出操作的业务数据中的关系,使应用程序代码更容易理解。

在理想情况下,数据应该在数据库中存储为纯 XML;但是即使数据存储在关系表中,仍然可以在应用程序中先将数据转换为 XML,然后再处理数据,这种做法在许多情况下是有意义的。

如果包装在对象层次结构中的数据结构可以用 XML 进行格式化,而且对象层次结构的主要用途是操作这些数据结构并向业务逻辑公开它们,那么可以考虑用 DOM 替代包装器对象层次结构。

本系列 的第 2 部分中,学习如何在自己的 DB2 应用程序中使用 XML 应用程序体系结构。

下载

描述 名字 大小 下载方法 用于 Java 的 DOM 和 XPath 包装器类
XMLParse.java 30KB HTTP
关于下载方法的信息


参考资料

学习

分享到:
评论

相关推荐

    DB2 9 基础(730 考试)认证指南,第 1 部分:DB2 规划.doc

    DB2 9 基础(730 考试)认证指南,第 1 部分:DB2 规划.doc

    用SQL查询DB2 XML数据

    本文介绍了很多数据库基础知识,提到了SQL/XML的几个关键方面,并展示了如何使用SQL/XML查询XML列中的数据。当然,除了这里讨论的用法外,用SQL和SQL/XML函数还可以做更多的事。本文给出了一个简单的Java例子,这个...

    DB2编程基础DB2编程基础DB2编程基础

    DB2编程基础要点DB2编程基础要点DB2编程基础要点DB2编程基础要点DB2编程基础要点DB2编程基础要点

    DB2-730中文教材--适合数据库开发人员以及对数据库有兴趣的人

    • 第 1 部分:DB2 规划 本教程介绍 DB2 9 产品和工具的基本知识,以及描述不同类型的数据应用程序、数据仓库和 OLAP 的概念。 • 第 2 部分:安全性 本教程介绍与 DB2 9 相关的身份验证、授权和特权概念。您应该...

    db2 9 730 中文教程

    • 第 1 部分:DB2 规划 本教程介绍 DB2 9 产品和工具的基本知识,以及描述不同类型的数据应用程序、数据仓库和 OLAP 的概念。 • 第 2 部分:安全性 本教程介绍与 DB2 9 相关的身份验证、授权和特权概念。您应该...

    DB2 pureXML 动态编程组合拳:iBatis+BeanUtils+JiBX

    DB2 pureXML 为管理 XML 数据提供了丰富的功能,在数据存储层面对 XML 提供了强有力的支持,这毫无疑问给软件开发人员带来了灵活性。而一个完整的应用程序除了数据存储层之外,还有数据访问层,业务逻辑层,界面展示...

    DB2 XML 查询开发实例解析

    本文将介绍 DB2 提供的一些基本 XML 函数,并结合一个简单的实例,重点介绍如何利用 DB2 提供的 XML 函数以视图或查询的形式灵活的实现 XML 文档的构造和发布。同时文中还将介绍利用作者编制的一个工具,根据目标 ...

    java连接DB2数据库编程简介

    java连接DB2数据库编程简介,包括基本的连接方法和实例

    一代数据库db2 9 对xml的支持

    一代数据库db2 9 对xml的支持 刘晶炜 pdf格式 看看

    DB2 9中基于Xquery和SQLXML的应用开发

    DB2 9中基于Xquery和SQLXML的应用开发

    db2-jdbc2-service.xml

    db2-jdbc2-service.xml,不错的东西!

    db2 xml best practise

    这是关于db2 xml方面的最佳实践,仅供参考

    搜索DB2中的XML文档的方法

    搜索DB2中的XML文档需要执行的任务分成两部分: 索引管理任务、全文搜索,本文简要讨论了这两种任务。

    为何选择DB2 9数据库XML成为靓点

    DB2 9对XML的支持与经典的关系数据模型相比所具有的优势是不可忽略的。与其他主流数据库管理系统比起来,DB2有其优势也有自己的不足。在处理datawarehouse系统上DB2的性能应该是非常优秀的,同时DB2对优化器做的相当...

    db2ese_c.lic DB2 V9.7 license linux x86_64

    emal:/opt/ibm/db2/V9.7/license # db2licm -l Product name: "DB2 Enterprise Server Edition" Expiry date: "Expired" Product identifier: "db2ese" Version information: "9.7" Enforcement policy: "Soft Stop...

    DB2 UDB 内存模型

    DB2 UDB 内存模型

    db2数据仓库db2数据仓库

    db2数据仓库db2数据仓库db2数据仓库db2数据仓库

    DB2 用户手册 官方 2

    第二部分 db2dmc90_数据移动使用程序指南和参考.pdf db2f0c90_系统监视器指南和参考.pdf db2hac90_数据恢复和高可用行指南与参考.pdf db2irc90_发行说明.pdf db2irc91_修订包1的发行说明.pdf db2isc90_服务器快速...

    db2 9 731 中文教材

    • 第 1 部分:服务器管理 学习管理 DB2 数据库服务器所需的技能。本教程提供了数据一致性,事务等方面的信息。 • 第 2 部分:数据放置 学习如何创建 DB2 数据库,以及存储表、索引、和数据的不同机制。本教程主要...

    db2 v9.5 企业版 License

    db2 v9.5 企业版 License,CPU选项的,好东东。大家用快点下。 看下面信息是否是真的了。 $ db2licm -l Product name: "DB2 Enterprise Server Edition" License type: "CPU 选项" Expiry date: "永久" Product ...

Global site tag (gtag.js) - Google Analytics