使用Databound组件访问数据库

在使用本教程之前,您需要在系统上安装含有 Web 和 Java EE 支持的 NetBeans IDE 6.0。熟悉 IDE 的各个基本部分并阅读 NetBeans 可视化 Web JSF 开发 了解 NetBeans IDE 开发环境的简要介绍。

本教程将涉及以下技术和资源:

JavaServer Faces 组件

Java EE 平台

1.2 与 Java EE 5*

1.1 与 J2EE 1.4

Travel 数据库 必 需

* 到本文发布之日时止,只有 Sun Java System Application Server 支持 Java EE 5。

本教程适用于 GlassFish V2 应用服务器。如果使用的是不同的服务器,请参阅 发行说明 和 常见问 题解答 了解各类问题和解决途径。有关所支持的服务器和 Java EE 平台的详细信息,请参阅 发行说明 。

创建含有下拉列表组件的页面

在本教程中,我们将构建一个 Travel Center 应用程序,如下图中部署的应用程序所示。

图 1:已部署的 Travel Center Web 应用程序

首先,我们将在新项目创建的默认的 Page 1.jsp 页面中添加一个 Table 组件和一个 Drop Down List 组件。

创建一个新 Web 应用程序项目,将它命名为 DataboundComponents,该应用程序使用 GlassFish V2 应用服务器和 Visual Web JavaServer Faces 框架。

IDE 将创建第一个页面,其名称为 Page1,并在 Visual Designer 中显示该页面。

展开 Palette 中的 Basic 节点,然后拖动一个 Label 组件到页面左侧。键入 Select Name: 并按 下回车键。

拖动一个 Drop Down List 组件到 Label 组件右侧。

在 Properties 窗口中,将 id 属性修改为 personIdDD。

按住 Ctrl-Shift 键的同时拖动 Drop Down List 组件到 Label 组件,将这两个组件关联到一起。

Label 组件的 for 属性现在已设置为 personIdDD。

从 Palette 窗口拖动一个 Message Group 组件到页面某角落中,比如说页面的右上角。

该组件可用于诊断编程错误。我们可以让诊断消息出现在该组件中,方法是调用 info(String)、 error(String)、 warn(String)和 fatal(String) 方法。Message Group 组件将显示 String 参数的值 。此外,关于运行时错误、验证错误和转换错误的消息将默认出现在该组件中。

将组件连接到数据库

Services 窗口位于 IDE 工作空间的左侧,其中含有一个 Databases 节点。Databases 节点将显示已 添加到 IDE 中的所有数据库驱动程序和连接。

NetBeans IDE 附带的 示例 Travel 数据库 出现在 Databases 节点下面。

将数据库绑到组件时,我们将在组件和数据库表之间创建两个层:RowSet 层和 Data Provider 层。 RowSet 层负责连接数据库、执行查询和管理结果集。Data Provider 层提供了一个公共接口用于访问许 多类型的数据,包括 rowsets、Array 对象和 Enterprise JavaBeans 对象。

通常,我们只有在需要设置查询参数时才会用到 RowSet 对象。在大多数其他情况下,我们应该使用 Data Provider 对象访问和操作数据。我们可以通过使用 Data Provider API 来降低学习门槛,因为相 同的 API 适用于封装任何类型的数据(也就是所使用的 Data Provider 实现)。

在本节中,我们将使用 Travel 数据库中的 PERSON 表为 Drop Down List 组件提供选择。

在 Services 窗口中,展开 Databases 节点,然后验证是否已连接到 TRAVEL 数据库。

如果 TRAVEL 数据库 jdbc 节点的标志是裂开的并且无法展开该节点,则表示 IDE 未连接到数据库。 要连接到 TRAVEL 数据库,右键单击 TRAVEL 数据库的 jdbc 节点并从弹出菜单中选择 Connect 选项。 如果出现 Connect 对话框, 则输入 travel 作为用户名和口令,选中 Remember Password During This Session 选项并单击 OK 按钮。如果未看到 TRAVEL 数据库的 jdbc 节点,则查看 如何在 NetBeans IDE 6.0 中启用 MySQL 示例 Travel 数据库 这篇文章了解如何将 IDE 连接到数据库。

展开 Travel > Tables 节点。

在 Tables 节点下面,我们可以看到数据库各个表的节点,比如说 CARRENTAL 和 FLIGHT。展开 Tables 节点的 Services 窗口如下图所示。

图 2:Services 窗口

将 Services 窗口中的 PERSON 拖动到 Drop Down List 组件上。

abc 文本将出现在 Drop Down List 组件中。 abc 文本表示显示字段已绑定到一个 String 对象,本 例中的 String 对象为 SQL 数据库中的一列,其类型为 varchar。此外,IDE 将为数据库表添加一个不 可见的 personDataProvider 组件。personDataProvider 组件将出现在 NavigaTor 窗口中。IDE 还会添 加一个 personRowSet 属性到 SessionBean1 中。

右键单击 Drop Down List 组件并从弹出菜单中选择 Bind to Data 选项。此时将出现 Bind to Data 对话框,如下图所示。

图 3:将数据绑定到 Drop Down List 组件

将数据绑定到 Drop Down List 组件时,我们必须指定在列表(Display Field)中显示的内容并且还 要指定底层程序(Value Field)所使用的值。通常,我们希望通过数据库表显示一些有意义的值,比如 说某人的姓名,但是也希望在底层程序中使用惟一的标识符。但是在此应用程序中,我们希望将 Value 值和 Display 值同时绑定到数据库中的同一列,即 PERSON.NAME 列,如以下两个步骤所示。

在 Bind to Data 对话框中,选择 Value Field 列表中的 PERSON.PERSONID 选项使组件的 getSelected 方法返回当前选择的 PERSON.PERSONID。

选择 Display 列表中的 PERSON.NAME,让浏览器使用 PERSON.NAME 数据库列中的值填充下拉列表。

单击 OK 按钮。

单击主工具栏中的 Run > Run Main Project 按钮。

IDE 将保存所有修改,然后编译、部署和运行应用程序。首先,Output 窗口将出现在 IDE 底部。IDE 会将编译和部署准备信息写入到该窗口中。如果在编译过程中遇到任何问题,请首先查阅 Output 窗口。 接下来,对话框将显示部署的状态信息。部署完成之后,IDE 将在 Web 浏览器中打开应用程序。浏览器 在呈现页面时会使用 PERSON 表的 NAME 列中的数据填充下拉列表。

添加表组件

接下来,我们将在应用程序中添加一个 Table 组件并将该组件连接到一个数据库表。

从 Palette 中拖动一个 Table 组件并将它放置在 Drop Down List 组件下面。

在 Services 窗口中,展开 Travel > Tables 节点。

将 Services 窗口中的 TRIP 拖动到 Table 组件标题栏上。

注意: 如果将 TRIP 数据库放置在表组件的其他部分上,则会打开 Choose Target 对话框。在 Choose Target 对话框中,选择 table1 选项并单击 OK 按钮。

右键单击 Table 组件并选择 Table Layout 选项。

Table Layout 框中的 Selected 列表将显示表中的所有列。我们将使用 Selected 列表中的项目指定 哪些列应显示在 Table 组件中。

使用 Ctrl-Click 组合键选择 Selected 列表中除 TRIP.DEPDATE、TRIP.DEPCITY 和 TRIP.DESTCITY 之外的所有条目。

单击 < 按钮。

所选条目已全部移至 Available 列表,只有以下三个条目仍然保留在 Selected 列表中,如下图所示 :

图 4:Table Layout 对话框

单击 OK 按钮。

此时,Visual Designer 将显示 Table 组件中的三列数据,如下图所示。

图 5:显示表列

修改 SQL 查询

接下来,我们将修改 tripRowSet 对象中的 SQL 查询,使查询也返回 TRIPTYPE 表中的数据。我们还 将修改 Table 组件,在其中显示旅行类型描述。

在 NavigaTor 窗口中,展开 SessionBean1 节点(如果该节点尚未展开)。

图 6:NavigaTor 窗口中的 SessionBean1 部分

在 NavigaTor 窗口的 SessionBean1 部分,右键单击 tripRowSet 节点并选择 Edit SQL Statement 选项。

Query EdiTor 将出现在编辑匹域,其中含有一个 tripRowSet 选项卡。

技巧 :如果 Output 窗口是打开的,则关闭它将更多的空间留给 Query EdiTor。

将 Services 窗口中的 Travel > Tables > TRIPTYPE 节点拖动到 Design View 中,如图 7 所示。

已有的两个表图中间将出现另一个表图,其中含有一个链接。该链接表示一对连接。 注意 IDE 修改 Source Code 面板中选择语句的方式。

清除 TRIPTYPE 表中的 PERSONID 复选框。

此操作将移除结果集和 SQL 查询(即 Source Code 面板)中的列,如下图所示:

图 7:Query EdiTor

让 Query EdiTor 继续打开。

单击编辑区域中的 Page 1 选项卡。

在 Visual Designer 中,右键单击 Table 组件并选择 Table Layout 选项。

此时将出现 Table Layout 对话框,由于我们已经修改了 tripRowSet 的 SQL 查询,因此可以显示更 多的列。

将 TRIPTYPE.DESCRIPTION 列添加到 Selected 列表中,然后单击 OK 按钮。

第四个列将出现在 Table 组件中。

控制所显示的行

为 TRIP 表添加了一个 Data Provider 之后,IDE 将创建一个 RowSet 对象,其中的 SQL 查询将为 表的所有列返回所有行。如果在此时部署并运行应用程序,则 Table 组件将在 TRIP 表中显示所有旅行 信息。

对于本文中的应用程序,Table 组件只显示与在 Drop Down List 组件中选择的人名相对应的旅行信 息。通过编辑 tripRowSet 对象的 SQL 查询在 Drop Down List 组件和 Table 组件之间创建一个主从复 合(master-detail)关系,我们限制了在数据库表中显示的信息。

单击编辑区域中的 jdbc:derby://localhost:1527/travel 选项卡,切换到 Query EdiTor。

在 Query EdiTor 的 Design Grid 中,右键单击 PERSONID 行中的任何表元并选择 Add Query Criteria 选项。

将 Comparison 下拉列表设置为 =Equals,选中 Parameter 单选按钮并单击 OK 按钮。

我们可以在 PERSONID 表的 Criteria 列中看到 =?,它会在 SQL 查询中添加以下 WHERE 语句。

代码示例 1:SQL 查询中的 WHERE 语句

WHERE TRAVEL.TRIP.PERSONID = ?

故障诊断技巧: 此时,我们可以验证查询是否已正确设置。在查询编辑器中单击鼠标右键,然后选择 Run Query 选项。在 Specify Parameters Value 对话框中,键入 1 作为 TRAVEL.TRIP.PERSONID 参数 的值,然后单击 OK 按钮。Person 1 查询的输出位于查询编辑器的结果面板中。

在 Query EdiTor 的 Design Grid 中,单击 DEPDATE 行中的 Sort Type 表元并从下拉列表中选择 Ascending 选项。

IDE 将自动设置 Sort Order 并将排序语句添加到 SQL 查询中。

关闭 Query EdiTor。

在 Visual Designer 中,右键单击 Drop Down List 组件。

Page1 类的源代码将在 Java EdiTor 中打开,并且光标将位于 personIdDD_processValueChange 方 法的主体中。IDE 将在首次双击 Drop Down List 组件时创建这个事件处理程序方法的主干程序( Stub )。

将 personIdDD_processValueChange 方法的主体替换为以下黑体代码。

代码示例 2:Drop Down List 组件的值修改事件处理

  public void personIdDD_processValueChange(ValueChangeEvent event) {   try {   getSessionBean1().getTripRowSet().setObject(   1, personIdDD.getSelected());   tripDataProvider.refresh();   } catch (Exception e) {   error("Cannot switch to person " +   personDataProvider.getValue(   "PERSON.PERSONID"));   log("Cannot switch to person " +   personDataProvider.getValue(   "PERSON.PERSONID"), e);   }   }

以上代码会将下拉列表中当前所选 NAME 的 PERSONID 值绑定到 tripRowSet 对象的准备 SQL 语句中 的参数,并执行查询以及获取新的结果集。

setObject 方法会将查询中的 ? 替换为 PERSONID 的值。 refresh 方法用于提交新查询和刷新结果 集。要了解有关这两个方法的更多信息,右键单击方法调用并从弹出菜单中选择 Show Javadoc 选项。查 看 Data Provider 和 RowSet Javadocs,方法是选择 Help > Javadoc References > Data Provider and Help > Javadoc References > RowSet 选项。

log 方法将发送一条消息和关联栈跟踪给应用服务器的日志,作用是帮助发现和诊断用户问题。查看 服务器日志的方法是右键单击 Services 窗口中的 server 节点并从弹出菜单中选择 View Server Log 选项。

按下 Alt-Shift-F 组合键重新格式化代码。

找到源代码中的 prerender 方法。

将 prerender 方法的主体替换为以下黑体代码。

代码示例 3:首次显示页面时同步主从数据

  public void prerender() {   if ( personIdDD.getSelected() == null ) {   try {   personDataProvider.cursorFirst();   getSessionBean1().getTripRowSet().setObject(   1, personDataProvider.getValue("PERSON.PERSONID"));   tripDataProvider.refresh();   } catch (Exception e) {   error("Cannot switch to person " +   personDataProvider.getValue("PERSON.PERSONID"));   log("Cannot switch to person " +   personDataProvider.getValue("PERSON.PERSONID"), e);   }   }   }

prerender 方法中的代码将在 Web 浏览器开始显示页面之前调用。

按下 Alt-Shift-F 组合键重新格式化代码。

单击编辑工具栏中的 Design 按钮,返回到 Visual Designer 中。

右键单击 Drop Down List 组件并选择 Auto-Submit on Change 选项。

在 Projects 窗口,以下代码将出现在 Onchange 属性中。

代码示例 4:onchange 属性代码

webuijsf.suntheme.common.timeoutSubmitForm(this.form, ‘personIdDD’);

现在,当用户在运行中的 Web 应用程序中修改下拉列表时,Web 浏览器将自动提交页面。

单击主工具栏中的 Run > Run Main Project 按钮。

IDE 将保存所有修改文件,重新编译应用程序将它重新部署到服务器中。

从 Drop Down List 组件中选择某个人物,查看 Table 组件是如何同步主从数据的。单击 DESTCITY 列头,查看 Table 组件如何对行排序。

更多功能

动手试试。添加一个 Static Text 组件到 Drop Down List 组件的右侧。右键单击 Static Text 组 件,并从弹出菜单中选择 Bind to Data 选项,然后将该组件绑定到 PERSON.JOBTITLE。运行程序并从下 拉列表中选择不同的姓名。注意到职位名并未发生变化。这是因为应用程序需要保持 personDataProvider 与下拉列表中的所选项目同步。将以下黑体代码添加到 prerender 方法中并重新运 行应用程序。现在,职位名应该与所选姓名一致了。

代码示例 5:同步 personDataProvider 与所选人名

  public void prerender() {   if ( personIdDD.getSelected() == null ) {   try {   personDataProvider.cursorFirst();   getSessionBean1().getTripRowSet().setObject(   1, personDataProvider.getValue("PERSON.PERSONID"));   tripDataProvider.refresh();   } catch (Exception e) {   error("Cannot switch to person " +   personDataProvider.getValue("PERSON.PERSONID"));   log("Cannot switch to person " +   personDataProvider.getValue("PERSON.PERSONID"), e);   }   }   else {   try {   // Synchronize data provider with current selection   personDataProvider.setCursorRow(   personDataProvider.findFirst(   "PERSON.PERSONID", personIdDD.getSelected()));   } catch (Exception e) {   error("Cannot switch to person " +   personIdDD.getSelected());   log("Cannot switch to person " +   personIdDD.getSelected(), e);   }   }   }

动手试试。 试着操作表的布局选项。右键单击 Table 组件并从弹出菜单中选择 Table Layout 选项 。将 Header Text 修改为 Departure Date、Departure City、Destination City 和 Description。使 用对话框中的 Options 表将表题设置为 Trips。选中 Enable Pagination 并将 Page Size 设置为 3。 运行应用程序并查看这些修改将如何影响表的显示方式。

注意: 如果要使用分页选项,将以下代码添加到 personIdDD_processValueChange 方法中的 tripDataProvider.refresh() 语句后面: tableRowGroup1.setFirst(0);。这样将确保从下拉列表中选 择新姓名时,第一个页面总是会显示出来,

动手试试。 构建一个含有 Drop Down List 组件和 Table 组件的应用程序。让 Drop Down List 组 件显示 TRIPTYPE.DESCRIPTION。让 Table 组件显示所有与所选 TRIPTYPE 含有相同 TRIPTYPEID 的 TRIP 记录。

动手试试。 您可能想希望 prerender 和 personIdDD_processValueChange 方法中的重复代码是否会 造成详细 Rowset 刷新两次。答案是否定的。要演示这一点,可以添加一个 log( method-name ) 语句到 构造函数、 prerender 方法和 personIdDD_processValueChange 中。 在 Services 窗口中,右键单击 某个 server 节点 并从弹出菜单中选择 View Server Log 选项。运行程序并选择一个新姓名。在服务器 日志(位于 Output 窗口)中,我们可以看到方法将按照以下顺序调用:

构造函数

prerender

构造函数

personIdDD_processValueChange

当浏览器首次请求页面时,应用程序会创建一个 Page1 实例并调用 prerender 方法。服务器将发送 响应(HTML 页面),并且 Page1 实例将被销毁。应用程序并不会调用值修改事件处理程序,因为应用程 序只有在提交页面时才会生成值修改事件。

从下拉列表中选择某个新姓名时,浏览器将提交页面。IDE 将创建一个新的 Page1 实例,并恢复前一 个实例的值(它们都在请求中传递)。因为这是一个提交事件,并且因为姓名已修改,所有应用程序将生 成一个值修改事件。这样会调用 personIdDD_processValueChange 方法,并且应用程序会刷新 Rowset。

调用值修改事件处理程序之后,应用程序将调用 prerender 方法。由于下拉列表现在已有选择的值, 因此应用程序将忽略 prerender 方法中的 if 部分。

结束语

将组件绑定到数据库表的步骤如下所示:

绑定一个组件到数据库表,方法是将数据库表的节点放置在组件上,或者从弹出菜单中选择 Bind to Data 选项并从下拉列表中选择一个已有的 Data Provider。

使用 Bind to Data 对话框配置组件所显示的数据库列。对于列表类型组件,还需配置所返回的数据 库列。我们还可以使用 Table Layout 菜单操作配置哪些数据库列将显示在 Table 组件中。

要修改 RowSet 对象中的 SQL 查询,可以在使用 Query EdiTor 打开 NavigaTor 窗口中的 RowSet 对象。

调用 RowSet 对象的 setObject 方法,设置查询参数的值。调用数据提供者的 refresh 方法,执行 查询并刷新结果集。

使用 Auto-Submit on Change 菜单操作让页面在组件值发生变化时自动提交。

执行以下步骤同步主从组件:

在 Page Bean 的 prerender 方法中添加代码,调用 RowSet 对象的 setObject 方法将查询参数设置 为一些默认值,比如说某个下拉列表中的第一个人物。然后,调用 refresh 方法执行查询。

将主结构(Master)组件绑定到 processValueChanged 方法。让这个方法调用从结构(Detail) RowSet 对象的 setObject 方法设置新查询参数。然后,调用 refresh 方法执行查询。

走过的路成为背后的风景,不能回头不能停留,若此刻停留,

使用Databound组件访问数据库

相关文章:

你感兴趣的文章:

标签云: