级别: 中级 Michael Galpin (mike.sr@gmail.com), 软件架构师, eBay
2008 年 1 月 03 日 更新 2008 年 10 月 06 日
本系列文章 介绍如何结合使用 XForms、IBM DB2 pureXML 和 Ruby 来简化 Web 应用程序的开发,分为四部分,这是第一部分。本系列文章中将开发一个虚构的应用程序来管理一个小型医院的门诊患者信息。您将看到每种技术的强大功能,同时还将看到如何将其结合起来。第一部分将说明 XForms、DB2 pureXML 和 Ruby on Rails 如何帮助您更快地构建以 XML 为核心的 Web 应用程序。
2008年10月更新: 根据读者和作者的反馈,对文章中“清单 1. 创建包含一个 XML 列的表”的第 1 行代码作如下修改, CREATE TABLE DOC.PATIENTS ( 更改为:CREATE TABLE xmlmd.PATIENTS ).
简介
技术世界在不断的变化。新技术层出不穷,原有的技术不断演化。这些力量产生了新的范型和最佳实践。有时候新技术就像是重新发明的轮子上闪闪发亮的油漆,但有时候又能带来切实的利益。这是 本系列文章 的第一部分,考察了有不少相通之处的三种新技术。这些技术从单纯的技术角度来看非常有趣,而且都以简化某些困难的任务为目标。我们将看到,XForms 是一种创建功能丰富的交互式 Web 应用程序的技术。还将考察用于管理 XML 文档的强大的 IBM® DB2® pureXML 特性。最后,我们将利用 Ruby on Rails Web 应用程序框架把两者结合起来,创建一个 Web 应用程序简化门诊患者信息的录入。请注意,本系列文章没有涉及到防止病人查看受限制的目录、通过要求登录保护医生和护士表单和特定区域诸如此类的安全问题,这些在产品环境中都是需要考虑的。
前提条件
本文假设读者对 XML 和 Web 应用程序有一定的了解。对 XForms、DB2 pureXML 和 Ruby on Rails 这三种核心技术事先有所涉猎当然最好,但不是必须的。本文使用 Mozilla XForms
插件版本 0.8.0.3 编写。该插件在任何 Mozilla 浏览器如 Firefox 中提供了 XForms 运行时支持。另一种非常有用的 Mozilla 插件是 XForms Buddy。它提供了一个 XForms 调试器。本文使用的是 0.5.6 版。还需要用到 IBM 的 DB2 数据库服务器。本文采用 DB2 Express-C 9.5。支持
Windows®、Linux™ 和 UNIX® 系统。此外还需要 Ruby on
Rails。本文使用了 Ruby 1.8.6 with Rails 1.2.5。下载链接参见 参考资料。
门诊的 XForms
这个管理门诊患者信息的应用程序,需要让患者输入数据,否则这些数据只能由办公室的工作人员采集。我们需要创建一个 Web 应用程序,这样任何能够运行 Web 浏览器的计算机都可作为患者的数据录入点。现在需要做出第一项技术决策,应用程序的用户界面将使用 XForms。
采用一种新技术仅仅是为了赶时髦或者为简历增加点炫耀的资本吗?完全不是。对于这种情况 XForms 非常适合。它可以用简单的 XML 模型定义数据,使用标准 HTML 表单元素定义视图。XForms 提供了这些元素之间的声明性映射。这意味着不需要编写任何客户端或服务器端代码接收提交的数据然后插入 XML 结构。XForms 替您完成了这些工作。而且是异步执行的:HTML 表单中的变化绑定到 XML 模型,然后发送到服务器实现同步。您享受到了 Ajax 的优点,而且不必编写任何 JavaScript 代码。
但是要记住,目前还不是所有的浏览器都支持 XForms。将来会如此,但现在还不行。因此还需要安装一个插件来支持它。如果应用程序的用户很多,这可能会造成问题。但是对于我们开发的这类专用应用程序而言足够了。用于访问应用程序的计算机是有限的,因此可以假设都安装了适当的浏览器和插件。
无论何时使用 XML,XForms 都是一种很强大的技术。这是一种客户端技术,因此在任何动态应用程序中还需要服务器端技术来支持它。后端需要持久数据的数据库。前端要使用 XML 表示数据,那么如果后端也使用 XML 岂不是更好?DB2 恰好能满足这个要求。
DB2 9 pureXML
如果曾经开发过使用 XML 的应用程序,很可能已经使用过两种常见的持久 XML 数据到数据库技术中的一种。第一种技术是使用某种 XML 关系映射技术。这种技术通常需要自己编写自定义的应用程序逻辑从 XML 文档中提取数据,然后放到关系数据库的表列中。通常被称为切割(shredding)。当然如果以后需要再次读取数据,还需要能够 “反切割” 并重新组装成 XML 文档。
另一种常见的技术是直接把 XML 文档转储到数据库的 CLOB 列中。实际上就是把 XML 看成是一个很长的字符串。此后就可以从数据库中读出,传递给解析器重建 XML 文档。一般来说这种办法要容易得多,因为不需要编写什么切割/反切割代码,但是功能差一些。没有非常有效的办法查询 XML 文档中的数据。
近年来 XML 数据库日渐普及,就是因为解决了这类问题。允许按照 XML 存储数据,因此不需要切割。同时又能使用 XQuery 高效查询,因此不会损失文档的结构。支持这种功能的多数数据库是小型的专用数据库,不过现在可以把 IBM 的旗舰数据库 DB2 添加到原生 XML 数据库的名单中了。
使用 DB2 可以在数据库中存储与 XForms 使用的 XML 相同的数据。不需要切割、映射或者解析数据。浏览器中的数据 “方言” 和数据库使用的方言一样。DB2 支持在 SQL 查询中使用 XQuery,称为 SQL/XML,因此可以方便地访问 XML 文档中的任何数据。比方说,假设需要使用患者的姓检索信息。可以将这些信息存储在 XML 文档中,编写 XQuery 根据患者的姓氏检索文档。我们来进一步看看 DB2 是如何做到的。
DB2 设置
现在需要设置 DB2,创建使用原生 XML 的表。和其他 XML 数据库相比,DB2
的一个优点是允许混合关系数据和 XML 数据。不需要非此即彼的选择,可以同时使用。因而不需要直接把 XML 文档映射到表,可以映射到列。表中给定的一行甚至可以包含多个 XML 文档。
可以通过两种不同的方法创建使用 XML 的新表。最简单的办法是使用命令行。清单 1 中的脚本创建只含一个 XML 列的表。
清单 1. 创建包含一个 XML 列的表
CREATE TABLE xmlmd.PATIENTS (
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (
START with +1 INCREMENT BY +1),
INFORMATION XML NOT NULL);
|
该例中的 INFORMATION 列的类型为 XML。可以看到,语法非常简单,和声明整数列或者 varchar 列没有什么区别。如果不喜欢使用命令行创建表,DB2 Command Center 提供了图形化的方式。可以使用它提供的创建表向导,如图 1 所示。
图 1. 启动创建表向导
单击 Create New Table 启动向导。打开图 2 所示的表名信息屏幕。
图 2. 命名表
命名新表的屏幕允许指定表的模式和表名。单击 Next 打开 Columns definition 界面,如图 3 所示。
图 3. 定义新表的列
单击 Add 按钮打开 Add Column 对话框,如图 4 所示。
图 4. Add column 对话框
这就是关键的地方了。要定义保存 XML 数据的列,必须把数据类型指定为 XML。仅此而已!向导的数据类型列表中已经包含 XML,没有什么特殊的地方。完成后单击 OK 将看到定义的 XML 列,如图 5 所示。
图 5. 增加的 XML 列
通过向导还可以添加更多的列、主键和外键等等。然后单击 Finish,表就创建好了。
无论用哪种方法创建表,都可用 SQL 向表中插入数据。编写 SQL 的时候可以把 XML 视作字符串,如清单 2 所示。
清单 2. 插入 XML
INSERT INTO DOC.PATIENTS(INFORMATION)
VALUES ('<?xml version="1.0" encoding="UTF-8"?>
<Info>
<FirstName>John</FirstName>
<Age>33</Age>
<Insurer>Blue Armor</Insurer>
<ID>555-88-1212</ID>
</Info>');
|
看起来似乎是插入一个简单的字符串,不过不用担心。DB2 不会将其看作是字符串。这和在查询中编写日期非常类似。按照特定的语法编写字符串,让数据库解析为特定的数据类型。如果语法错误,查询将失败。处理 XML 的方式是一样的。使用 SQL 和 XQuery 还可以查询 XML,如清单 3 所示。
清单 3. SQL/XML Query
SELECT XMLQUERY('<Patients>
{for $i in $x/Info
where $i/Insurer = "Blue Armor"
return <Patient>{$i/FirstName/text()}</Patient>}
</Patients>'
passing P.INFORMATION as "x") from DOC.PATIENTS P;
|
注意这里把 SQL (SELECTION ... from ...) 和 XQuery 混合在一起了。被称为 SQL/XML。关键在于使用 XMLQUERY 保留字表明要通过 SQL 选择语句执行针对传入 XML 文档的 XQuery。运行该查询将返回清单 4 所示的 XML 文档。
清单 4. 结果 XML 文档
<?xml version="1.0" encoding="UTF-16"?>
<Patients>
<Patient>John</Patient>
</Patients>
|
现在您看到使用 DB2 原生存储 XML 是多么简单,但是在 XForms 使用的 XML 和 DB2 中的 XML 之间还需要点什么。我们将使用 Ruby。
Rails 和 DB2
现在需要考虑如何将 XForms 前端和 DB2 pureXML 后端连接在一起了。Ruby on Rails 为快速便捷地创建 Web 应用程序提供了一种强大的方法。而且处理数据库也很方便,但是 Rails 能用于 DB2 尤其是 DB2 pureXML 吗?当然可以,而且和 Rails 的其他方面一样,惊人的简单。
为 Ruby 安装 DB2 驱动程序
首先需要启动 Rails 中的 DB2 支持。如果已经安装了 Rails,还需要安装 Ruby Gems。否则应该安装它,因为这个包管理系统非常适合为 Rails 增加新的功能,如 DB2 支持。安装之后在命令提示符下输入:>gem install ibm_db。
从而下载 DB2 Ruby 驱动程序。安装完成后,所有的 Ruby 应用程序(不仅仅是 Rails 应用程序)都有了 DB2 支持。如果使用的是 Windows,就会提示选择什么版本的驱动程序,如清单 5 所示。
清单 5. 选择 DB2 驱动程序
>gem install ibm_db
Bulk updating Gem source index for: http://gems.rubyforge.org
Select which gem to install for your platform (i386-mswin32)
1. ibm_db 0.6.0 (mswin32)
2. ibm_db 0.6.0 (ruby)
3. ibm_db 0.4.6 (ruby)
4. ibm_db 0.4.6 (mswin32)
5. Skip this gem
6. Cancel installation
|
需要选择最新版本的驱动程序,因此选择 #1 或 #2。如果使用 Windows 安装程序安装了 Ruby,需要选择 #1。现在就可以创建使用 DB2 pureXML 的 Rails 应用程序了。
创建 Rails 应用程序
Rails 开发人员应该熟悉下面的代码。我们将创建清单 6 所示的应用程序。
清单 6. 创建 Rails 应用程序
>rails xmlmd
create
create app/controllers
create app/helpers
create app/models
create app/views/layouts
create config/environments
create components
create db
create doc
create lib
create lib/tasks
create log
create public/images
create public/javascripts
create public/stylesheets
create script/performance
create script/process
create test/fixtures
create test/functional
create test/integration
create test/mocks/development
create test/mocks/test
create test/unit
create vendor
create vendor/plugins
create tmp/sessions
create tmp/sockets
create tmp/cache
create tmp/pids
create Rakefile
create README
create app/controllers/application.rb
create app/helpers/application_helper.rb
create test/test_helper.rb
create config/database.yml
create config/routes.rb
create public/.htaccess
create config/boot.rb
create config/environment.rb
create config/environments/production.rb
create config/environments/development.rb
create config/environments/test.rb
create script/about
create script/breakpointer
create script/console
create script/destroy
create script/generate
create script/performance/benchmarker
create script/performance/profiler
create script/process/reaper
create script/process/spawner
create script/process/inspector
create script/runner
create script/server
create script/plugin
create public/dispatch.rb
create public/dispatch.cgi
create public/dispatch.fcgi
create public/404.html
create public/500.html
create public/index.html
create public/favicon.ico
create public/robots.txt
create public/images/rails.png
create public/javascripts/prototype.js
create public/javascripts/effects.js
create public/javascripts/dragdrop.js
create public/javascripts/controls.js
create public/javascripts/application.js
create doc/README_FOR_APP
create log/server.log
create log/production.log
create log/development.log
create log/test.log
|
这样就完成了 Web 应用程序的框架。还需要编辑 config/database.yml 以便连接到 DB2,如清单 7 所示。
清单 7. 编辑 config/database.yml
# IBM DB2 Database configuration file
# Install the IBM DB2 driver and get assistance from:
# http://www.alphaworks.ibm.com/tech/db2onrails
development:
adapter: ibm_db
database: health
username: michael
password: your_password_here
schema: xmlmd
# == remote TCP/IP connection (required when no local database catalog entry available)
# host: bigserver // fully qualified hostname or IP address
# port: 50000 // data server TCP/IP port number
# Warning: The database defined as 'test' will be erased and
# re-generated from your development database when you run 'rake'.
# Do not set this db to the same as development or production.
test:
adapter: mysql
database: xmlmd_test
username: root
password:
host: localhost
production:
adapter: mysql
database: xmlmd_production
username: root
password:
host: localhost
|
请注意该例中只修改了开发设置,而没有改变测试和产品设置。此外把 adapter 设为 ibm_db。这就是刚刚安装的驱动程序。Rails 不知道这个驱动程序,因为它不是 Rails 默认安装的驱动程序。所幸的是很容易修改。只需要编辑一个文件。找到 Ruby 安装目录打开文件 /lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record.rb。找到 RAILS_CONNECTION_ADAPTERS 这一行,在列表的后面加上 ibm_db,如清单 8 所示。
清单 8. 为 Rails 增加 DB2 支持
RAILS_CONNECTION_ADAPTERS = %w( mysql postgresql sqlite firebird sqlserver db2 oracle
sybase openbase frontbase ibm_db )
|
现在可以生成使用 XML 的模型了。首先按照常规方式使用 Rails 生成脚本建立一个模型,如清单 9 所示。
清单 9. 生成 Rails 模型
>ruby script\generate model doctor
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/doctor.rb
create test/unit/doctor_test.rb
create test/fixtures/doctors.yml
create db/migrate
create db/migrate/001_create_doctors.rb
|
生成的迁移脚本和预期的一样。我们将利用它生成使用 XML 的另一个表,如清单 10 所示。
清单 10. Rails 迁移脚本:001_create_doctors.rb
class CreateDoctors < ActiveRecord::Migration
def self.up
create_table :doctors do |t|
t.column :profile, :xml, :null => false
end
end
def self.down
drop_table :doctors
end
end
|
这是非常典型的 Rails 迁移脚本。仅定义了一列 “profile”。惟一特别的一点是将列的类型定义为 xml。我们已经使用 Rails 创建了连接到数据库的 Ruby 脚本,并建立了包含 XML 列的表。剩下的就是测试脚本了。
测试 Ruby 和 DB2
测试 Ruby/DB2 pureXML 脚本很容易。不过是一般的 Rails 迁移罢了。我们使用 Ruby 的 rake 命令,如清单 11 所示。
清单 11. 运行迁移脚本
>rake db:migrate
(in /xmlmd)
== CreateDoctors: migrating ===================================================
-- create_table(:doctors)
-> 0.7840s
== CreateDoctors: migrated (0.7860s) ==========================================
|
这样就完成了。您也许希望使用 --trace 选项帮助调试错误。一般来说,对于诊断连接错误、用户名/口令错误、指定的数据库或模式错误等,非常有效。下面需要使用 DB2 检查是否存在新建表,如清单 12 所示。
清单 12. 检查和描述新表
db2 => describe table xmlmd.doctors
Data type Column
Column name schema Data type name Length Scale Nulls
------------------------------- --------- ------------------- ---------- ----- ------
ID SYSIBM INTEGER 4 0 No
PROFILE SYSIBM XML 0 0 No
2 record(s) selected.
|
由此可见,我们已经使用 Ruby
on Rails 建立了包含 XML 列的 DB2 表。此后就可以使用 Rails 完成很多有趣的工作了。可以创建新的迁移脚本向数据库插入 XML 数据。Ruby 创建 XML 文档特别简单,只需要转化成字符串并发送给 DB2。稍加修改还可以利用 Rails 中的脚手架来处理 XML。
结束语
本系列的第一部分说明了如何利用 XForms、DB2 pureXML 和 Ruby on
Rails 快速构建以 XML 为核心的 Web 应用程序。考察了
XForms 如何简化了交互式前端的创建。交互性类似于
Ajax,但是不需要编写 JavaScript 或映射代码。我们还介绍了使用 DB2 pureXML 存储和查询 XML 是多么简单。DB2 的 SQL/XML 允许混合使用 SQL 和 XQuery,可以方便地访问数据库中的 XML 数据。最后还介绍了如何设置 Ruby on Rails 与 DB2 pureXML 交互。稍加调整技能使用 Ruby on Rails 创建支持 XML 的 DB2 表了。所有技术的关键部分都已完结。下一部分我们将使用 XForms、DB2 pureXML 和 Ruby on Rails 创建用于医院门诊管理的 Web 应用程序。
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| 第 1 部分的样例代码 | part1_doctorsOffice.zip | 2KB | HTTP |
|---|
参考资料 学习
获得产品和技术
讨论
关于作者  | |  | Michael Galpin 从 1998 年开始开发 Web 应用程序,他从 California Institute of Technology 获得了数学学位。他是位于 San Jose, CA. 的 eBay 公司的架构师。 |
对本文的评价
|