级别: 中级 Doug Monroe (monroe@sqnt.com), 系统管理咨询师, MichaelDKelly.com Martin C Brown (questions@mcslp.com ), 自由撰稿人和顾问, MCslp
2007 年 8 月 23 日 在 AIX® 中可以开发使用 Java™ 和 PHP 技术的应用程序。在获得使用 PHP 作为基于 Web 的接口平台的好处的同时,您可以使用 Java 编程语言编写核心逻辑(或者重新部署现有的基于 Java 的应用程序)。在本文(系列文章的第 3 部分)中,介绍了如何将第 2 部分中创建的核心应用程序连接到 DB2® 数据库,以便对问卷调查的问题和回答进行存储。
关于本系列
PHP 是一种非常优秀的 Web 开发语言,而在商业应用程序开发方面,Java™ 编程语言十分流行。因此,为了在 AIX® Version 5.3 操作系统上充分利用它们的优势,专门开发了 PHP Java Bridge。本系列文章的目的是使得 AIX 5.3 开发人员能够更快地在 Web 应用程序的开发中集成 PHP 和 Java 技术。
为了说明这一点,您将按照典型的开发过程来构建一个简单的问卷调查应用程序,具体内容包括:
- 开发主要的 Java 应用程序
- 通过 Servlet 将 Java 应用程序公开为基于 Java 的 Web 应用程序
- 添加在数据库中存储信息的支持
- 将原始应用程序公开为 Web 服务,并为该应用程序提供 PHP 接口
- 使用专门的 PHP Java Bridge 重新开发 PHP 接口
本系列文章共分为六个部分:
-
第 1 部分介绍了一个应用程序,并为构建 Java 应用程序以及使用 Tomcat 执行基于 Java 的 Web 应用程序设置了相应的环境。
-
第 2 部分介绍了主要的应用程序代码以及一个简单的 Java Servlet 的开发,以便为信息提供一个 Web 接口。
- 第 3 部分将核心应用程序连接到 DB2® 数据库,以便对问卷调查的问题和回答进行存储。
- 第 4 部分对原始应用程序进行转换,使其能够作为 Web 服务进行访问,并且它为 PHP 接口提供了基础。
- 第 5 部分使用 PHP Java Bridge 为 Java 应用程序构建了 PHP 接口。
- 第 6 部分对这个应用程序进行重新开发,以便使用 PHP Java Bridge 来代替 Web 服务接口。
引言
本文将第 2 部分中创建的 Java 业务应用程序与 DB2 Version 9 数据库集成在一起。数据提交到 Java 业务应用程序,并且您可以使用所存储的数据来提供关于问卷调查回答的统计信息。
本文的内容包括:
- 问卷调查应用程序中数据库的使用
- 安装 DB2
- 数据库结构
- 创建数据库表
- 向表中插入数据
- 根据所存储的数据提供报表
数据库角色
在一个类似这样的应用程序中,数据库角色可以在不同的级别上起到作用。从数据捕获和存储的角度来看,它为您的应用程序实现数据的存储提供了一种简单方法。对于存储信息,有许多可行的解决方案,从使用基本的文本文件,直到使用完全成熟的关系数据库解决方案,比如 IBM DB2 数据库服务器。
对于与本文中类似的基于 Web 的应用程序来说,使用文本文件存储数据的做法并不实用,因为极有可能会出现并发访问的情况。使用专业的数据库解决方案,可以通过数据库引擎来解决锁定和数据损坏的问题。
更重要的是,从由数据库中重新获取信息的角度来看,您可以使用数据库引擎以执行查询、排序和计算,这将省去执行聚合和统计分析(可能需要与数据库进行大量的数据交换)的需要。相反,您可以使用数据库引擎来处理这个过程,然后报告汇总的信息,而不是原始数据。
您需要使用数据库来存储问卷调查表格中的原始数据,并且作为您的应用程序报告相关信息的一种方法。
在 AIX 中安装DB2 Version 9
尽管 AIX 分发介质中提供了 DB2 Version 8,但是我们仍然决定使用 DB2 Version 9,这是因为您稍后可能需要利用 DB2 Version 9 PureXML 功能。IBM 为 DB2 Version 9 Enterprise Server 提供了 90 天的试用期。参考资料中提供了相关的评估、系统需求和安装文档的链接。
要在 AIX 中安装 DB2 Version 9,您需要 64 位的内核、Technology Level 5300-04、Service Pack 5300-04-02 和 C++ 运行时 level xlC.rte 8.0.0.4。
要检查您的 AIX 5L™ pSeries® 服务器,您可以使用 oslevel -s 命令,如果发现所使用的是 Technology Level 5300.0.3,这就意味着您需要对其进行更新。请参见参考资料以获取有关 AIX 更新的链接。
对于 C++ 运行时,可以使用 lslpp 来显示您的系统中当前所安装的版本。所以,如果使用 lslpp -L xlC.rte 显示服务器中 C++ 运行时的版本为 6.0.0.0,这同样意味着您需要对其进行更新。请参见参考资料获取 Fix Central 的链接以便进行更新。
如果您尚未安装浏览器,现在可以先安装一个 Web 浏览器。可以从 IBM 下载用于 AIX 的 Mozilla 版本(请参见参考资料)。
DB2 Version 9 的安装过程非常简单。要运行 GUI 方式的安装,您需要一个 X-windows 接口。
- 下载相关的软件,并复制到您的 AIX 系统。必须进行注册,但可以免费注册。该文件的名称为 db2_v9_ese_aix.tar.gz。
- 以 root 用户的身份,解压缩 gzip tar 镜像并进行安装(请参见清单 1)。
清单 1. 解压缩并安装 DB2
# gunzip -c db2_v9_ese_aix.tar.gz | tar -xvf -
# cd ese_t/disk1
# ./db2setup
|
在 Launchpad 页面中,您可以单击左边的链接,以查看 DB2 文档(需要 Web 浏览器)。
- 要继续进行安装,可以单击 Install a Product 项目。
- 单击 Install New to enter the DB2 Setup Wizard。这个向导将引导您完成余下的安装步骤。
在安装的过程中,需要注意以下几点:
- DB2 的缺省安装目录是 /opt/IBM/db2/V9.1。安装需要至少 474MB 的磁盘空间。在我的服务器上,/opt 中没有这么大的空间,所以我选择创建一个新的文件系统 /DB2,以便进行本文中的实验。我建立了相应的安装目录 /DB2/V9.1。
- 安装向导在系统中为数据库管理员创建了登录信息。在缺省情况下,您所创建的数据库将位于这些实例所有者用户的 home 目录中。我选择将这些 home 目录放到 /DB2 中,这样一来,这个 home 目录路径就成了 /DB2/home。
继续完成安装向导,将 DB2 Enterprise Server 安装到您的系统中。
通过安装示例数据库对安装进行测试。要完成这项任务,可以使用“db2inst1”进行登录,然后执行下面的操作(其中,用粗体显示了相关的命令):
- 使用
db2start 命令启动数据库管理器(请参见清单 2)。
清单 2. 运行 db2stsart 命令
$ db2start
06/09/2007 12:46:46 0 0 SQL1063N DB2START processing was successful.
SQL1063N DB2START processing was successful.
|
- 使用
db2sampl 命令创建示例数据库(请参见清单 3)。
清单 3. 创建示例数据库
$ db2sampl
Creating database "SAMPLE"...
Connecting to database "SAMPLE"...
Creating tables and data in schema "DB2INST1"...
'db2sampl' processing complete.
|
- 通过连接到数据库并执行一项查询来验证是否创建了数据库(请参见清单 4)。
清单 4. 验证是否创建了数据库
$ db2
(c) Copyright IBM Corporation 1993,2002
Command Line Processor for DB2 ADCL 9.1.0
db2 => connect to sample
Database Connection Information
Database server = DB2/AIX64 9.1.0
SQL authorization ID = DB2INST1
Local database alias = SAMPLE
db2 => select * from staff where dept = 20
ID NAME DEPT JOB YEARS SALARY COMM
------ --------- ------ ----- ------ --------- ---------
10 Sanders 20 Mgr 7 98357.50 -
20 Pernal 20 Sales 8 78171.25 612.45
80 James 20 Clerk - 43504.60 128.20
190 Sneider 20 Clerk 8 34252.75 126.50
4 record(s) selected.
db2 => quit
DB20000I The QUIT command completed successfully.
$
|
在安装了 DB2 之后,您可以考虑将其与应用程序进行集成。
使用 Java 业务应用程序连接到 DB2 数据库
要在 Java 业务应用程序中连接到数据库,最佳的解决方案是使用 Java Database Connectivity (JDBC) 接口。JDBC 是一种数据库接口,它独立于任何提供了 JDBC 兼容驱动程序的数据库系统,并且对于最终目标数据库平台无法确定的应用程序来说,使用它进行开发是非常实际的解决方案。
对于您正在完成的工作,它是连接到您的 DB2 安装的最有效方法。在清单 5 中,您可以看到使用 JDBC 所连接到的 DB2 数据库的基本结构,以及相应的 Java 业务应用程序。
清单 5. 简单的 JDBC 连接
import java.sql.*;
public class PHPJavaAddData {
public static void main(String[] args) {
Connection conn = null;
try {
Class.forName("com.ibm.db2.jcc.DB2Driver");
conn =
DriverManager.getConnection("jdbc:db2://localhost:50000/SURVEY","db2inst","s
urveypw");
System.out.println("Yay, connected");
} catch (Exception ex) {
System.out.println("SQLException: " + ex.getMessage());
}
}
}
|
连接 URL(getConnection() 方法中提供的字符串)定义了数据库 (DB2)、数据库服务器的主机名、数据库名、连接时所使用的用户名和密码。
要编译和运行这些 JDBC 示例,可以使用实例所有者登录帐号“db2inst1”,并将密码设置为“surveypw”。您需要修改这个用户的环境,以包含 java5 二进制文件的路径,并且将 DB2 JDBC jar 文件设置为类路径。您还需要主要的 JDBC jar 文件以及附带的许可证,可以在 Java 目录对其进行访问。要实现这一点,以“db2inst1”登录并执行下面的命令:
$ PATH=/usr/java5_64/bin:$PATH
$ export PATH
$ CLASSPATH=/DB2/V9.1/java/db2jcc.jar:/DB2/V9.1/java/db2jcc_license_cu.jar:.
$ export CLASSPATH |
您可能希望对 db2inst1 的配置文件进行相应的更改,以便当您注销时能够保留这些更改。
然后,您需要创建“SURVEY”数据库:
$ db2 create database SURVEY |
对于其中的每个示例,编译并执行下面列出的代码,如下所示(上述清单的示例文件名为“PHPJavaAddData.java”):
$ javac PHPJavaAddData.java
$ java PHPJavaAddData |
在您开始添加数据之前,您需要创建数据库结构。
创建数据库结构
数据库结构需要能够保存问卷调查的结果,然后允许您对所存储的数据进行查询和报告。还需要以合适的方式进行存储,以便您可以对输出结果生成有价值的统计信息。
根据您的问卷调查的复杂程度的不同,数据库的结构也可能差别很大。对于单个的、简单的问卷调查,您可以将每个问题的所有信息放到单个表的一个字段中。这就要求问卷调查和相应的表是固定的,或者至少是保持同步的,因为即使对问卷调查进行很小的更改(已经编码到 Java 业务应用程序的类中),都可能需要对该表中用于这个问卷调查的相应字段进行更改。
这意味着,您需要创建一种更加灵活的结构,以便能够接受更灵活的输入(与问卷调查的格式一致),即创建单个表来保存结果,该表中的每一行仅包含有关一个问题的信息。
要标识单个问卷调查(例如,单个用户)的所有回答(对于每个问题),您还需要使用一种方式来标识单独一组回答以及不同的问卷调查问题回答。该方法应该允许您从数据库中提取信息,以便查询单个用户的整个问卷调查回答,以及汇总排序多个问卷调查的回答。
您可以从图 1 中看到基本的数据库结构。
图 1. 简单的数据库结构
第一个表 survey_response,用于标识单个问卷调查的回答,其中的唯一的 ID(使用连续的数据类型)用于标识每个问卷调查以及需要回答的问题。在这个示例结构中,仅定义了一个字段,即唯一的 ID,数据库将自动生成这个值。您将使用这个唯一的 ID 来标识 survey_response_detail 表中实际问卷调查问题回答的组。您不能在 survey_response_detail 中使用自动递增的字段,因为这个值应该对于一组问题回答是唯一的。因为您在一行中存储一个问题回答,所以每个问题都应该有一个新的 ID,而不是每个问卷调查一个 ID,后者并不是我们想要的。
很显然,这个表目前的格式仅包含一个字段,它看起来根本没什么用处,但是您可以在这个表中存储附加的信息,如回答者的电子邮件地址或者用于不同问卷调查的其他标识信息。
清单 6 中的 Java 类 CreateDB,创建了您所需要的数据库表。
清单 6. 为我们的应用程序创建数据库表
import java.sql.*;
public class CreateDB {
public static void main(String[] args) {
Connection conn = null;
try {
Class.forName("com.ibm.db2.jcc.DB2Driver");
conn =
DriverManager.getConnection("jdbc:db2://localhost:50000/SURV
EY",
"db2inst1","surveypw");
Statement s = conn.createStatement ();
s.executeUpdate ("CREATE TABLE survey_response (" +
"responseid int GENERATED ALWAYS AS IDENTITY
PRIMARY KEY" +
")");
s.executeUpdate ("CREATE TABLE survey_response_detail (" +
"responseid int, " +
"question int, " +
"subquestion int, " +
"responsenumeric int," +
"responsestring varchar(40)" +
")");
s.close ();
} catch (Exception ex) {
System.out.println("SQLException: " + ex.getMessage());
}
}
}
|
现在,让我们来看看如何在数据库中对信息进行存储和组织,以及在接收到问卷调查回答时如何更新信息。
向数据库中添加结果
要将结果添加到数据库中,您需要获得已经完成的问卷调查的唯一 ID,您可以使用 survey_results 表中自动递增的值。向表中添加信息,需要运行合适的 INSERT 语句。
在您的 Web 应用程序中,您需要执行以下这三个步骤:
- 在 Servlet 的
init() 函数中,打开到数据库的连接。
- 通过向 survey_response 表中插入一个“空”行以获得回答 ID (responseid) 的数值,即获取自动生成的值。
- 对于该问卷调查中的每个问题,向数据库中插入一行数据。
第一个步骤非常简单,您在所创建的 Servlet 类中添加一个连接参数,然后使用这个连接示例,如上所述,打开该连接,如下面的清单 7 所示。
清单 7. 更新 init() 函数
public void init(javax.servlet.ServletConfig config) {
this.survey.add(new SurveyQuestionText("Name",
"Enter your full name"));
this.survey.add(new SurveyQuestionRadio("Favourite colour",
"Enter your favourite colour",
new String[] {"Red", "Blue", "Green"}));
try {
Class.forName("com.ibm.db2.jcc.DB2Driver");
conn =
DriverManager.getConnection("jdbc:db2://localhost:50000/SURVEY","db2inst","s
urveypw");
} catch (Exception ex) {
System.out.println("SQLException: " + ex.getMessage());
}
}
|
要获得唯一的回答 ID,您需要向该表中插入一行,以便生成一个可以使用的新的 ID。这个 ID 是由数据库引擎自动创建的,并且自动地递增,从而确保它是唯一的 ID。当您提交该语句时,您必须添加 RETURN_GENERATED_KEYS 选项,这将返回自动生成的值。
然后,您可以使用 getGeneratedKeys() 方法来接受这个自动生成的 ID。这将返回一个 resultset 对象,您需要这个过程所返回的第一个值,以获得新的唯一的 ID。清单 8 显示了这个过程的代码。
清单 8. 为每个问卷调查获得唯一的 ID
try {
s = conn.createStatement();
s.executeUpdate(
"INSERT INTO survey_response (responseid) "
+ "values (0)",
Statement.RETURN_GENERATED_KEYS);
rs = s.getGeneratedKeys();
if (rs.next()) {
responseid = rs.getInt(1);
} else {
System.out.println("Can't get auto incremement data");
out.println("Sorry, we couldn't write your responses into the DB");
}
rs.close();
s.close ();
} catch (Exception ex) {
System.out.println("SQLException (getting responseid): " +
ex.getMessage());
}
|
最后,您必须通过确定合适的 INSERT 语句来插入信息,并将数据写入到数据库中。必须对每个问卷调查问题完成这项操作,所以,您可以在相同的循环(以前是 Servlet 的一部分,用于输出问卷调查结果)中执行这项操作(请参见清单 9)。
清单 9. 插入问卷调查数据
for(Iterator<SurveyQuestion> i = this.survey.iterator(); i.hasNext(); ) {
SurveyQuestion question = (SurveyQuestion) i.next();
question.showquestion(out,false);
out.println("<p>" + request.getParameter("field" + fieldid));
try {
ps = conn.prepareStatement (
"INSERT INTO survey_response_detail " +
"(responseid, question, responsestring) VALUES(?,?,?)");
ps.setString (1,responseid.toString());
ps.setString (2,fieldid.toString());
ps.setString (3,request.getParameter("field" + fieldid));
int count = ps.executeUpdate ();
ps.close ();
} catch (Exception ex) {
System.out.println("SQLException (adding question result): " +
ex.getMessage());
}
fieldid++;
}
|
我们在上面的代码中使用了一个预编译语句,以使得能够更容易地在查询中填充相关的数据。我们本可以使用一个预编译语句并且每次重新设置数据,但是为了保持完整性,我们决定在每次循环的时候重新创建它。
从数据库中生成结果的统计信息
尽管并不是当前应用程序中的关键部分,但是应该研究如何恢复信息,以查看这个数据库结构是否正确。
您可以使用数据库来提供关于问题回答(您可以编写合适的 SQL 查询来获取该信息)的统计信息。例如,使用下面的清单 10 中的查询,您可以从数据库中查询最喜欢的颜色是红色(问题 2)的回答者的数目。
清单 10. 查询最喜欢的颜色是红色的回答者的数目
SELECT count(responsestring) FROM survey_response_detail
WHERE question = 2 AND
responsestring = 'red'
|
这个查询提供了单个结果,即对于问题 2 回答“red”的所有回答者的计数。
或者,您可以使用 GROUP BY 子句,获得所有不同颜色的汇总信息。这样可以根据指定字段的唯一元素对数据进行分类。因此,您可以重新编写一个查询,使其返回特定字段中每个项目的计数,并根据该字段中的唯一值进行分组,在这个示例中是回答字符串 (responsestring)。清单 11 中的查询返回问题 2 的 responsestring 字段中每个唯一值的计数。
清单 11. 返回 responsestring 字段的每个唯一值的计数
SELECT count(responseid),responsestring FROM survey_response_detail
WHERE question = 2
GROUP BY responsestring
|
现在,您可以获得一个多行的结果集,其中每一行表示一个唯一值(红色、蓝色和绿色),并且得到该值在表中的出现次数计数。
使用数据库来存储问卷调查的问题
既然您可以使用数据库来存储调查结果,那么同样可以使用数据库来存储问卷调查的问题。很难在本文有限的篇幅内详细地介绍一个非常复杂的问卷调查系统,但是您可以想象一下,对问卷调查的问题使用一个简单结构的表,其中包括问题编号和问题类型,并使用另一个表来保持可能的问题选项(使用单选按钮或多选按钮来处理问题类型)。您可以在图 2 中看到这个基本的布局。
图 2. 问卷调查问题的数据库结构
通过对数据库运行一个 SELECT 查询,并创建执行该应用程序中的其他部分所需的对象,就可以在 Servlet 的 init() 块中生成问卷调查的问题。
总结
在本文中,您了解了如何扩展问卷调查应用程序的功能,以便可以将信息存储到数据库中。首先,您了解了如何安装 DB2 数据库引擎,然后研究需要向数据库中存储哪些信息,以及存储这些信息需要什么样的数据库结构。
在后半部分中,您使用将相关信息写入到数据库中所需的信息,扩展了原始的 WebSurvey 类 Servlet。您还简要地了解了如何使用这些存储在数据库中的信息来获得统计信息,毫无疑问,这是问卷调查应用程序的关键。
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| Part 3 source code | au-surveydb.zip | 6KB | HTTP |
|---|
参考资料 学习
获得产品和技术
讨论
作者简介  | |  | Doug Monroe 是 DMA Inc. 的一名 UNIX 系统管理咨询师和教员。他拥有俄勒冈州立大学的计算机科学学士学位,自从 1984 年以来一直在支持各种风格的 UNIX。您可以通过 monroe@sqnt.com 与他联系。 |
 | |  | Martin Brown 成为一名职业作家已经有 8 年多的时间了。他是很多书籍和文章的作者,内容涉及很多主题。他的特长包括很多开发语言和平台 —— Perl、Python、Java、JavaScript、Basic、Pascal、Modula-2、C、C++、Rebol、Gawk、Shellscript、Windows、Solaris、Linux、BeOS、Mac OS/X 等等 —— 还包括 Web 编程、系统管理和集成。他会定期为 ServerWatch.com、LinuxToday.com 和 IBM developerWorks 撰写文章,在 Computerworld、Apple Blog 以及其他站点都会定期更新自己的 blogger,同时还为 Microsoft 撰写一些主题文章。您可以通过 questions@mcslp.com 与他联系。 |
对本文的评价
|