执行插入、更新和删除操作
本教程介绍如何使用 NetBeans IDE 6.5 和 JSF 1.2 (Woodstock) 组件构建能够创建、检索、更新和删除数据库行的 Web 应用程序。该应用程序提供了一个主数据下拉列表和一个同步的详细信息表。该应用程序的用户能够从关联数据库添加、更新和删除详细信息表中的记录。
本教程使用的概念在更基本的教程中有介绍。如果您对 IDE 及其设计组件尚未有基本的了解,请先阅读一些介绍性教程,如可视化 Web JSF 应用程序开发入门和使用数据绑定组件访问数据库。
预计时间:45 分钟
目录

要学习本教程,您需要具备以下软件和资源。
* 要利用 NetBeans IDE 的 Java EE 5 功能,请使用完全符合 Java EE 5 规范的应用服务器,例如 GlassFish Application Server V2 UR2。如果使用的是其他服务器,请查阅发行说明和常见问题解答,了解已知问题和解决方法。有关支持的服务器和 Java EE 平台的详细信息,请参见发行说明
有关使用其他数据库完成本教程的信息,请参见插入、更新和删除 wiki。
创建项目
在本教程中,您将创建一个包含单个页面的 Web 应用程序。首先需要对页面进行布局,该页面包括一个人及其相应行程,如下图所示。

设计页面
- 创建一个使用可视化 Web JavaServer Faces 框架且名为
InsertUpdateDelete 的新 Java Web 应用程序。该应用程序的 Page1.jsp 文件将在可视设计器中打开。
- 从组件面板的“WoodStock 基本”部分拖放一个“下拉列表”组件到页面的左上角。在“属性”窗口中,将其
id 属性更改为 personDD。
- 右键双击“下拉列表”组件并选择“添加绑定属性”。
-
从组件面板的“Woodstock 基本”部分拖放一个“消息组”组件到下拉列表的右侧 。
“消息组”组件显示验证错误和转换错误,以及通过 info 和 error 方法写入 Java Server Faces 上下文中的消息。这些消息有助于调试项目。
- 在其他两个组件下面放置一个“表”组件。
-
在“导航”窗口中,展开 "Page1" 节点直至看到 form1 组件。 右键单击 "form1" 节点并选择“添加绑定属性”。

设置数据库
在本节中,您将在 IDE 中设置 Travel 数据库和 MySQL 数据库服务器。
- 请确认您的机器已经安装并正在运行 MySQL 数据库服务器。有关连接到 MySQL 数据库的更多信息,请参见连接到 MySQL 数据库
-
在“服务”窗口中,右键单击“MySQL 服务器”节点,然后选择“创建数据库”。
此时将打开“创建新的数据库”对话框。

-
从“新数据库名”下拉列表中,选择“样例数据库:travel”并单击“确定”。
Travel 数据库将出现在“服务”窗口的“MySQL 服务”节点下面。

配置下拉列表
-
打开“服务”窗口,展开“数据库”节点,连接到 Travel 数据库。
如果 Travel 数据库标记的 jdbc 节点是断开的
,并且不能展开节点,则表示 IDE 并未连接到数据库。 右键单击 Travel 的 jdbc 节点,并从弹出式菜单中选择“连接”
-
展开 Travel 数据库的 jdbc 节点,然后展开“表”节点。
注意:在本教程的余下部分中,将把 Travel 数据库的 jdbc 节点称作 Travel 节点。
-
将 person 节点拖放到可视设计器的“下拉列表”组件中。
“导航”窗口中的 Page1 部分显示了一个 personDataProvider 节点,SessionBean1 部分中显示了一个 personRowSet 节点。
-
右键单击“下拉列表”组件,并从弹出式菜单中选择“更改时自动提交”。
此设置导致的结果是,只要从该列表中选定一个新值就会将该页面发送至服务器。
-
右键单击“下拉列表”组件,并从弹出式菜单中选择“配置虚拟表单”。
请注意在随后出现的对话框中,personDD 出现在窗口的左上角,表示已选定下拉列表。
-
单击“新建”并在“名称”字段中键入 person。双击 Participate 列下面的字段并将其设置为 Yes,对 Submit 列执行相同操作,如下图所示。
通过使用虚拟表单,该应用程序避免了在“表”中进行不必要的数据验证。
- 单击“确定”。
-
在可视设计器工具栏中单击“显示虚拟表单”按钮
,如下图所示。
查看虚拟表单,您可以看到可视设计器组件和其他配置过的虚拟表单间的关系。
配置表
-
将“服务”窗口中的 "travel > Tables > trip" 节点拖放至可视设计器的“表”组件上。
如果经提示要选择一个目标组件来接收拖放的节点,请选择 table1 并单击“确定”。
-
右键单击“表”组件并从弹出式菜单中选择“表布局”
“表布局”对话框示了刚创建的 tripDataProvider 中的可用字段,让您控制在表中显示哪些字段。
-
使用 < 按钮将 trip.tripid、trip.personid 和 trip.lastupdated 从右侧的“已选定”列表中移除,如下图所示。
- 单击“选项”标签,将“标题”更改为
Trips Summary,并单击“确定”。
-
可视设计器中的“表”组件在外观上应与下图一致。注意如果您的列的顺序与图示中不同,可以通过重新打开“表布局”对话框,单击“列”标签并使用“向上”和“向下”按钮来对列进行重新排列。
-
在“导航”窗口中,右键单击 SessionBean1 下面的 tripRowSet,并从弹出式菜单中选择“编辑 SQL 语句”。
此时将打开 SQL 查询编辑器。
-
在靠近窗口中间的网格区,右键单击 personid 行并选择“添加查询条件”,如下图所示。
-
在“添加查询条件”对话框中,将“比较”下拉列表设置为 =Equals 并选中“参数”单选按钮,然后单击“确定”。
字符 =? 出现在 PERSONID 的条件字段中,"WHERE TRAVEL.TRIP.PERSONID=?" 出现在编辑器底部 SQL 面板的 SQL 语句的结尾处。
- 关闭 tripRowSet 的 SQL 编辑器。
更改列组件
现在,将列内容更改为可编辑字段,准备好添加将新行程插入到数据库中的新功能。这样,通过将其他组件嵌入到“表”组件中,您就利用了“表”组件的复合性质
-
右键单击“表”组件并选择“表布局”。
此时将打开“表布局”对话框。
-
在“列”标签中,从右侧的“已选定”列表中选择 trip.depdate。在对话框底部的“列详细信息”处,将“组件类型”从静态文本改为文本字段,如下图所示,单击“应用”。
- 对 trip.depcity 和 trip.destcity 执行相同操作。
- 从“已选定”列表中选择 trip.triptypeid 并将“组件类型”从“静态文本”更改为“下拉列表”。
- 单击“确定”。
-
将 "Travel > Tables > triptype" 节点拖放至“表”组件中的“下拉列表”。如果打开了“选择目标”对话框,请选择 dropDown1 并单击“确定”。
此操作将创建 triptypeDataProvider。
为“表”配置“虚拟表单”
接下来,为表中的输入组件创建一个虚拟表单。虚拟表单确保:当对 personDD 下拉列表的更改提交至该页面时,可不对输入组件进行验证和转换。只要用户从下拉列表中选择一个新人,表中就会显示正确信息。
- 在导航窗口中,在表中使用 Ctrl-Click 组合键从三个包含文本字段的列中选择三个“文本字段”组件,从triptypeid 列中选择“下拉列表”组件。
- 右键单击一个选定的组件并从弹出式菜单中选择“配置虚拟表单”。
- 在“配置虚拟表单”对话框中,请确保三个“文本字段”和“下拉列表”列出在窗口的左上角。如果与下图所列内容不一致,请关闭对话框,重新选择,再试一次。若正确列示,请单击“新建”。
-
将新虚拟表单的名称更改为 save,将 Participate 设置的名称更改为 Yes,如下图所示,然后单击“确定”。
添加“事件”和“初始化”代码
现在,将 “personDD下拉列表”组件与“表”组件关联起来,以实现以下行为:当用户从列表中选择一个人时,该人的行程将出现在表中。
- 双击“personDD 下拉列表”组件以创建一个值更改事件方法并在该方法中打开 Java 编辑器。
-
在 personDD_processValueChange 方法中,将 粗体 文本添加到代码样例 1 中,然后按下 Alt-Shift-F 重新设置代码。
| 代码样例 1:下拉列表事件处理程序 |
public void personDD_processValueChange(ValueChangeEvent event) { Object selectedPersonId = personDD.getSelected(); try { personDataProvider.setCursorRow( personDataProvider.findFirst("PERSON.PERSONID", selectedPersonId)); getSessionBean1().getTripRowSet().setObject(1, selectedPersonId); tripDataProvider.refresh(); form1.discardSubmittedValues("save"); } catch (Exception e) { error("Cannot switch to person " + selectedPersonId); log("Cannot switch to person " + selectedPersonId, e); } }
|
在 try 子句中,form1.discardSubmittedValues("save") 语句保证了:只要用户从下拉列表中选择新的人,表中显示的当前行程信息将被和该选定人相关的新信息所替换。回想:表中所有显示行程信息的用户界面元素都在名为 save 的虚拟表单中。
还需注意,事件处理程序并未抛出异常。 而是将其记录到 server.log 文件中。 事件处理程序也调用了一个 error 方法,即:在错误事件中,在“消息组”组件中显示消息。
注意:在 Oracle 数据库中,将 PERSONID 前面的 PERSON 忽略掉。
-
在 Java 源代码中,找到 prerender 方法,或者使用 Ctrl-F 组合键搜索 prerender。 将以下 粗体 代码添加到该方法中。
| 代码样例 2:Prerender 方法 |
public void prerender() { if ( personDD.getSelected() == null ) { Object firstPersonId = null; try { personDataProvider.cursorFirst(); firstPersonId = personDataProvider.getValue("PERSON.PERSONID"); personDD.setSelected(firstPersonId); getSessionBean1().getTripRowSet().setObject( 1, firstPersonId); tripDataProvider.refresh(); } catch (Exception e) { error("Cannot switch to person " + firstPersonId); log("Cannot switch to person " + firstPersonId, e); } } }
|
注意:在 Oracle 数据库中,将 PERSONID 前面的 PERSON 忽略掉。
- 在 Java 编辑器中单击鼠标右键,选择“格式”将代码正确对齐。
测试应用程序 - 第 1 部分
单击主工具栏中的“运行主项目”按钮
,运行项目。
注意:缺省情况下,创建项目时会启用保存时编译功能,因此在 IDE 中运行应用程序无需首先编译代码。有关保存时编译功能的更多信息,请参见创建、导入和配置 Java 项目指南的“保存时编译”一节。
该页面加载到浏览器后,下拉列表中填充有姓名,且表中填有数据。 从列表中选择一个不同的姓名时,和该姓名相关的行程将出现在表中。
添加插入功能
在本节中,您将添加一项功能,实现通过向数据库插入一个行集来向表中添加一项行程。首先,为表的文本字段提供“消息”组件。这些组件确保用户在输入不正确的信息时能看到错误。然后,向页面添加一个“按钮”组件,使用户能够向数据缓冲区添加新行。
向“表”中添加更多组件。
- 单击“设计”按钮,在“可视设计器”中查看 Page1。
- 从“组件面板”的 Woodstock 基本节,将一个“消息”组件拖至该表前三列中每列最顶部的文本字段。
- 选择第一个“消息”组件。在“属性”窗口中,滚动至
for 属性并从下拉列表中选择 textField1。 当该消息和文本字段正确关联起来时,消息文本发生改变显示这种关联,如下图所示。
- 将第二个“消息”组件的
for 属性设为 textField2。
-
将第三个“消息”组件的 for 属性设为 textField3。
确保您的应用程序的外观如下图所示。
- 从“组件面板”的“Woodstock 基本”部分中,拖放一个“按钮”组件到 Page1 中,并将其置于“表”组件上,靠近第二列顶部。
注意:存在一个已知的问题,会对 IE7 中 JSF 1.2 按钮组件的宽度造成影响。解决方案是将该“按钮”组件置于一个布局组件(“网格面板”、“组面板”或“布局面板”)中。重新设定布局组件的大小会自动重新设定“按钮”组件的大小。
- 更改
按钮中的文本,以添加行程。
- 在“属性”窗口中,将按钮的
id 属性设置为 add。
- 右键单击“按钮”组件并选择 添加绑定属性。
- 在可视设计器中,双击该按钮打开 Java 编辑器,使该按钮的插入点位于
add_action 事件处理方法。
-
将下面以粗体显示的代码添加到该按钮的事件处理方法中:
| 样例代码 3:添加行程操作代码 |
public String add_action() { try { RowKey rk = tripDataProvider.appendRow(); tripDataProvider.setCursorRow(rk); tripDataProvider.setValue("TRIP.TRIPID", new Integer(0)); tripDataProvider.setValue("TRIP.PERSONID", personDD.getSelected()); tripDataProvider.setValue("TRIP.TRIPTYPEID", new Integer(1)); } catch (Exception ex) { log("Error Description", ex); error(ex.getMessage()); } return null; }
|
注意:对于 Oracle 数据库,请忽略 setvalue 语句中的 TRIP。
-
双击 Java 编辑器并选择“修复导入”以解决找不到 RowKey 的错误。
IDE 将下面的包添加到导入语句的 Page1.java 块中:
导入 com.sun.data.provider.RowKey;
测试应用程序 - 第 2 部分
单击“运行主项目”按钮运行该项目
。
注意:缺省情况下,创建项目时会启用保存时编译功能,因此在 IDE 中运行应用程序无需首先编译代码。有关保存时编译功能的更多信息,请参见创建、导入和配置 Java 项目指南的“保存时编译”一节。
Web 浏览器将加载该页面,并且显示了“添加行程”按钮,如下图所示。每次单击该按钮时,表的底部就新添加一行空行。您可以编辑行中的信息,但由于您尚未提供保存行集的机制,当从下拉列表中选择一个不同姓名时,所做更改将丢失。
修改页面以保存行集
在本节中,您将向该项目添加第二个行集。该行集用于计算使用的最大行程 ID。
创建 maxTripRowSet
- 单击编辑器窗口的“设计”,返回到可视设计器的 Page1。
-
打开“服务”窗口,选择 "Databases > travel > Tables > trip table",将其拖放到导航窗口的 SessionBean1 节点上。
此操作将为 SessionBean1 创建两个新的子节点:tripDataProvider 和 tripRowSet1。
-
在“添加新数据提供器”对话框中,选中“创建 SessionBean1/tripRowSet1”单选按钮,将数据提供器名称更改为 maxTripRowSet,单击“确定”。
此操作将在 SessionBean1 中创建 maxTripDataProvider 和 maxTripRowSet。
- 在导航窗口中,双击 "SessionBean1 > maxTripRowSet" 以打开“查询编辑器”。单击“源代码”面板(顶部往下第三个面板)。删除在该处找到的现有 SQL 查询并输入以下查询:
从行程中选择 MAX(trip.tripid)+1 作为 MAXTRIPID
针对下一步要添加的“保存”按钮,使用操作处理程序中的 MAXTRIPID 值。
注意:对于 Oracle 数据库,请忽略 trip 前缀。
-
关闭“查询编辑器”。
注意:“查询编辑器”的图形编辑器不支持此查询。如果看到一个提示词法错误的警告对话框,您可以单击“继续”将其安全地关闭。</
将用户更改保存到数据库中
- 在“表”组件上面靠近第一列顶部的位置放一个“按钮”组件。
- 将按钮的文本由“
按钮”更改为“保存更改”。
- 右键单击按钮组件并选择 “添加绑定属性”。
- 在“属性”窗口中,将其
id 属性更改为 save。
- 右键单击“保存更改按钮”并从弹出式菜单中选择“配置虚拟表单”
- 在“配置虚拟表单”对话框中,确保
save 显示于列表的左上角,这样您在此窗口中做的更改将应用到“保存更改按钮”。然后,选择保存虚拟表单,将“提交”值更改为 "Yes",单击“确定”。
- 在可视设计器中,双击“保存更改按钮”以打开 Java 编辑器。在 Java 编辑器中,该按钮的插入点位于
save_action 事件处理方法中。
-
将下面以粗体显示的代码添加到该按钮的事件处理方法中:
| 代码样例 4:保存操作代码 |
public String save_action() { try { // Get the next key, using result of query on MaxTrip data provider CachedRowSetDataProvider maxTrip = getSessionBean1().getMaxTripDataProvider(); maxTrip.refresh(); maxTrip.cursorFirst(); long newTripId = ((Long) maxTrip.getValue("MAXTRIPID")); // Navigate through rows with data provider if (tripDataProvider.getRowCount() > 0) { tripDataProvider.cursorFirst(); do { if (tripDataProvider.getValue("TRIP.TRIPID").equals (new Long(0))) { tripDataProvider.setValue("TRIP.TRIPID", new Long(newTripId)); newTripId++; } } while (tripDataProvider.cursorNext()); } tripDataProvider.commitChanges(); } catch (Exception ex) { log("Error Description", ex); error("Error :"+ex.getMessage()); } return null; }
|
注意:对于 Oracle 数据库,忽略 setValue 语句中的 TRIP。 对于 Java DB 数据库,使用 Integer 代替 Long。
测试应用程序 - 第 3 部分
单击“运行主项目”按钮运行该项目。
注意:缺省情况下,创建项目时会启用保存时编译功能,因此在 IDE 中运行应用程序无需首先编译代码。有关保存时编译功能的更多信息,请参见创建、导入和配置 Java 项目指南的“保存时编译”一节。
该应用程序功能如下所示:
- 您可以添加并保存行程。该行程随后出现并保留在表中。如果选择一个不同的人,然后再返回到此人,就会看到您添加的行程。
- 可编辑现有行程信息并保存更改。
- 若在日期字段输入非日期信息,应用程序将提供一条错误消息。
- 在保存前您可以多次单击“添加行程”,作为一次性添加多行的简便方法。保存更改时仍为空的行将作为空行保存。
- 如果在单击“保存更改”前转向一个不同的人,将丢失所做的所有更新。
- 如果修改一些值,然后单击一个列头根据该列进行排序,“表”组件会记住即将做的更改,该更改随后将被保存。
添加删除功能
在本节中,您将为表添加删除功能。用户可使用此功能通过移除数据库中的一行来删除一项行程。如本教程所示,“删除”按钮的操作是直接的,并不需要“保存更改”按钮来删除数据库中的行。事实上,由于“删除”按钮事件处理程序使用 commitChanges 方法,它也保存了所有即将做出的更改,正如“保存更改”按钮所做的那样。
为每行添加一个“删除按钮”
-
在编辑器窗口中单击“设计”,返回到可视设计器的 Page1,然后右键单击 "Trips Summary" 表并从弹出式菜单中选择“表布局”。
此时将打开“表布局”对话框。
- 单击“新建”创建新列。
-
在“已选定”列表中选择新列的列名之后,请在“列详细信息”处做出以下更改:
- 页眉和页脚文本:删除“页眉和页脚”文本字段中的任何缺省文本,保留空白。
- 组件类型:
按钮
- 值表达式:
删除
- 宽度:删除任何缺省值并保留空白。
- 水平对齐:
居中
- 垂直对齐:
居中
- 单击“确定”。
- 选择表格中最顶端的“删除”按钮,并在“属性窗口”中,将
id 属性的值设置为 delete。
添加事件代码。
- 右键单击表列中最顶端的按钮组件,并选择“添加绑定属性”。
- 在“导航窗口”中,展开 Page1 节点直到你能看见 TableRowGroup1 组件。右键单击 TableRowGroup1 并选择 添加绑定属性。
- 双击“删除”列的第一个按钮来打开 Java 编辑器,焦点处于
delete_action 事件处理方法中。
-
将下面以粗体显示的代码添加到该按钮的事件处理方法中:
| 代码样例 5:删除操作代码 |
public String delete_action() { form1.discardSubmittedValues("save"); try { RowKey rk = tableRowGroup1.getRowKey(); if (rk != null) { tripDataProvider.removeRow(rk); tripDataProvider.commitChanges(); tripDataProvider.refresh();} } catch (Exception ex) { log("ErrorDescription", ex); error(ex.getMessage()); } return null; }
|
测试应用程序 - 第 4 部分
单击“运行主项目”按钮运行该项目。
注意: 缺省情况下,创建项目时会启用保存时编译功能,因此在 IDE 中运行应用程序无需首先编译代码。欲了解更多有关保存时编译功能的信息,请参见创建、导入和配置 Java 项目指南的“保存时编译”一节。
下图显示了运行中的应用程序。
部署后,应能从表中删除一行,从而将其从数据库中移除。删除操作也将进行所有即将对数据库做的更改。
添加还原功能
现在,为页面添加还原功能。使用此功能,用户将能够放弃编辑还原到之前保存过的数据。请注意,还原功能不会返回已保存或已删除的行;“保存更改”按钮和“删除”按钮都会更改数据库。
添加还原更改按钮
- 在编辑器窗口中单击“设计”,返回到可视设计器的 Page1,然后从“组件面板”拖放一个“按钮”组件到 Page1。 将新“按钮”置于“添加行程按钮”右侧。
- 将按钮的文本更改为“
还原更改”。
- 在属性窗口中,将“按钮”组件的
id 属性更改为 revert。
- 右键单击“按钮”组件并选择“添加绑定属性”。
- 双击“还原更改”按钮,在 Java 编辑器中打开
revert_action 方法 。
-
将下面代码样例中以粗体显示的代码添加到 revert_action 方法中。
| 代码样例 6:还原操作代码 |
public String revert_action() { form1.discardSubmittedValues("save"); try { tripDataProvider.refresh(); } catch (Exception ex) { log("Error Description", ex); error(ex.getMessage()); } return null; }
|
配置虚拟表单
当前配置的应用程序出现了一些不良行为。例如,如果用户在现有行的第一列输入一个无效日期,然后单击“添加”按钮,操作则会失败,这是因为日期转换错误阻止了表单提交。用户单击“添加”按钮时,其期待的行为是:放弃处理表的输入字段,这样就可以不考虑即将对现有表进行的编辑而添加新行。
同样,用户单击“还原”按钮时,其目的是为了放弃所有编辑操作,因此在该情况下也要忽略编辑操作。然而,用户单击“删除”按钮时,仍需进行验证,这是因为此按钮不仅删除行,还提交即将做出的更改,这就要求先处理该输入字段。
为确保在用户单击“添加”或“还原”按钮时,页面的输入字段放弃处理(包括验证检查),应使这些按钮提交一份虚拟表单。可使这两个按钮提交同一份虚拟表单,因为它们都需要提交一份无内容的虚拟表单。
-
在“导航”窗口中,展开 Page1 节点,以查看所有组件。选择“添加”、“还原”和“删除”按钮,然后单击鼠标右键并从弹出式菜单中选择“配置虚拟表单”。
在“配置虚拟表单”窗口中,添加、还原和删除应出现在左上角,以显示该按钮的选定状态。
-
在“配置虚拟表单”窗口中,单击“新建”,将新虚拟表单命名为 add/revert/delete,将“提交”设置为 "Yes"。 单击“确定”。
测试应用程序 - 第 5 部分
单击“运行主项目”按钮运行该项目
。
注意:缺省情况下,创建项目时会启用保存时编译功能,因此在 IDE 中运行应用程序无需首先编译代码。有关保存时编译功能的更多信息,请参见创建、导入和配置 Java 项目指南的“保存时编译”一节。
下图显示了运行中的应用程序。
部署后,您将能够执行以下功能:
- 从下拉列表中选择一个姓名,显示该人的行程摘要。
- 编辑现有行程信息并将更改保存至数据库。
- 用不正确的日期格式编辑现有行程信息,单击“添加行程”添加新行,或单击“还原更改”放弃编辑。
- 为表添加新行,添加行程字段,将更改保存至数据库。
- 从表(和数据库中)中删除一行。
-
放弃所做编辑在数据库中还原至最近保存过的数据。
结束语
在本教程中,您将“表”组件、“文本字段”组件和“下拉列表”组件和数据库的信息关联起来。您设置了组件属性,添加 prerender 和事件代码以从数据库中插入、更新和删除数据,并还原输入表单的更改。使用了虚拟表单,使应用程序可只使用一个页面,也使在添加行或还原更改时提交的数据绕过验证检查。
另请参见
本页的最后修改时间:2008 年 10 月 22 日