了解应用程序
既然您的项目已包含了实体类、用于控制实体类的 EJB 会话 Bean 和 JSF 驱动的用于显示和修改数据库的前端,那么请尝试运行该项目以查看结果。
以下是一系列可选的小练习,可用来进一步熟悉应用程序,以及 IDE 所提供的功能。
检查已完成的项目
- 要运行此项目,可以在“项目”窗口中右键单击项目节点并选择“运行”,也可以单击主工具栏上的“运行项目”(
) 按钮。
当显示应用程序的欢迎页面时,将提供一个链接列表,用于查看包含在每个数据库表中的条目。
当完成了“通过实体类创建 JSF 页”向导时,链接将被添加到欢迎页面 (index.xhtml
)。这些链接将作为 Facelets 页(为“咨询机构”数据库提供 CRUD 功能)的入口点。<h:body> Hello from Facelets <h:form> <h:commandLink action="/address/List" value="Show All Address Items"/> </h:form> <h:form> <h:commandLink action="/billable/List" value="Show All Billable Items"/> </h:form> <h:form> <h:commandLink action="/client/List" value="Show All Client Items"/> </h:form> <h:form> <h:commandLink action="/consultant/List" value="Show All Consultant Items"/> </h:form> <h:form> <h:commandLink action="/consultantStatus/List" value="Show All ConsultantStatus Items"/> </h:form> <h:form> <h:commandLink action="/project/List" value="Show All Project Items"/> </h:form> <h:form> <h:commandLink action="/recruiter/List" value="Show All Recruiter Items"/> </h:form> </h:body>
- 单击 "
Show All Consultant Items
" 链接。查看上面的代码,则可以看到目标页为/consultant/List.xhtml
。(在 JSF 2.0 中,由于隐式导航所以文件扩展名是推断出来的。)
数据库目前不包含任何样例数据。可以通过单击 "Create New Consultant
" 链接和使用提供的 Web 表单手动添加数据。此操作将触发/consultant/Create.xhtml
页进行显示。还在 IDE 中运行 SQL 脚本以使用样例数据填充表。以下子部分对这两个选项进行了说明。
您可以单击索引链接返回到欢迎页面列出的链接。这些链接提供了保存在每个数据库表中数据的视图,并触发了每个实体文件夹中 List.xhtml
文件的显示。稍后会有说明,在将数据添加到表之后,会显示其他链接,其中每个条目都允许您查看 (View.xhtml
)、编辑 (Edit.xhmtl
) 和销毁单个表记录的数据。
使用 SQL 脚本来填充数据库
运行提供的脚本,该脚本会生成数据库表的样例数据。脚本 (mysql_insert_data_consult.sql
) 包含在咨询机构数据库 zip 文件中,该文件可从所需软件表中下载。
根据所使用的数据库服务器(MySQL 或 JavaDB),您可以运行提供的脚本,该脚本会为数据库表生成样例数据。对于 MySQL,该脚本为mysql_insert_data_consult.sql
。对于 JavaDB,该脚本为 javadb_insert_data_consult.sql
。两个脚本分别包含在各自的归档文件中,可以通过所需软件表进行下载。
- 从主菜单中选择“文件”>“打开文件”,然后导航到脚本在您的计算机上的位置。单击“打开”。文件会自动在 IDE 的 SQL 编辑器中打开。
- 确保在 SQL 编辑器工具栏的“连接”下拉列表中选择了
consult
数据库。
可以在编辑器中右键单击并选择“运行语句”,也可以单击“运行 SQL”() 按钮。您可以在“输出”窗口中查看脚本运行的结果。
- 重新启动 GlassFish 服务器。这是使服务器可以重新装入和缓存
consult
数据库中包含的新数据所必需的步骤。为此,请单击“输出”窗口中的 GlassFish 服务器标签(GlassFish 服务器标签显示服务器日志),然后单击左旁注中的“重新启动服务器”() 按钮。GlassFish 服务器即会停止,然后重新启动。
- 重新运行项目,然后单击 "
Show All Consultant Items
" 链接。将看到该列表不再为空。
NetBeans 数据库支持
可以使用 IDE 的数据库表查看器来显示和修改直接在数据库中维护的表数据。例如,右键单击“服务”窗口中的
consultant
表,然后选择“查看数据”。在编辑器的顶部将显示用于执行操作的 SQL 查询,下面则显示表的图形视图。
在表单元格内双击以对数据进行内联修改。单击“提交记录”(
) 图标以将更改提交到数据库。
图形视图提供了更多的功能。有关详细信息,请参见 NetBeans IDE 6.5 中数据库支持的改进。
了解 Facelets 页中的编辑器支持
- 在编辑器中打开
/consultant/List.xhtml
页。第 8 行表明该页的呈现依赖于 Faceletstemplate.xhtml
文件。<ui:composition template="/template.xhtml">
要显示行号,请右键单击编辑器的左旁注,然后选择“显示行号”。
- 使用 IDE 的“转至文件”对话框来打开
template.xhtml
。按 Alt-Shift-O 组合键(在 Mac 上为 Ctrl-Shift-O 组合键),然后开始键入template
。
单击“确定”(或按 Enter 键)。 - 模板将使用
<ui:insert>
标记将其他文件的内容插入到其标题和正文中。将光标置于<ui:insert>
标记上,然后按 Ctrl-空格键调用文档弹出式窗口。
可以在 JSF 标记及其属性上按 Ctrl-空格键调用文档弹出式窗口。您查看的文档是从正式的 JSF 标记库文档所提供的描述中获取的。 - 切换回
List.xhtml
文件(按 Ctrl-Tab 组合键)。<ui:define>
标记用来定义将应用于模板标题和正文的内容。为每个实体类生成的所有 4 个 Facelets 文件(Create.xhtml
、Edit.xhtml
、List.xhtml
和View.xhtml
)都使用了此模式。 - 将您的光标置于任何 EL 表达式(用于包含在
Bundle.properties
文件中的本地化消息)上。按 Ctrl-空格键查看本地化消息。
在上图上,可以看到 EL 表达式解析为 "List
",该表达式将应用到模板标题,并且可以从呈现在浏览器中的页面得到验证。 - 滚动到文件底部并找到
Create New Consultant
链接的代码(第 92 行)。如下所示:<h:commandLink action="#{consultantController.prepareCreate}" value="#{bundle.ListConsultantCreateLink}"/>
- 在
commandLink
的action
属性上按 Ctrl-空格键以调用文档弹出式窗口。action
属性表示在浏览器中单击链接时处理请求的方法。将提供以下文档:
方法表达式,用于表示在用户激活此组件时要调用的应用程序操作。该表达式的值必须为一个没有参数且返回对象(调用其 toString() 以派生逻辑结果)的公共方法,该对象将被传递到此应用程序的 NavigationHandler。
换句话说,action
值通常是指 JSF 受管 Bean 中的一个方法,其值为String
。然后 JSF 的NavigationHandler
会使用该字符串将请求转发到相应的视图中。可通过以下步骤来验证这一点。 - 将光标置于
consultantController
上,然后按 Ctrl-空格键。编辑器的代码完成表明consultantController
是一个 JSF 受管 Bean。 - 将光标移动到
prepareCreate
,然后按 Ctrl-空格键。代码完成列出了包含在ConsultantController
受管 Bean 中的方法。 - 按 Ctrl 键(在 Mac 上为 ⌘ 键),然后将鼠标悬停在
prepareCreate
上。形成了一个链接,您可以直接导航至ConsultantController
受管 Bean 中的prepareCreate()
方法。 - 单击链接并查看
prepareCreate()
方法(如下所示)。public String prepareCreate() { current = new Consultant(); selectedItemIndex = -1; return "Create"; }
该方法将返回Create
。NavigationHandler
在后台收集信息,并将Create
字符串应用于以视图(为响应请求而发送)为目标的路径:/consultant/Create.xhtml
。(在 JSF 2.0 中,由于隐式导航所以文件扩展名是推断出来的。)
通过字段验证来了解数据库完整性
- 在浏览器的 Consultants List 页中,单击 "
Create New Consultant
" 链接。正如之前子部分中的说明,此操作将触发呈现/consultant/Create.xhtml
页。 - 在表单中输入以下详细信息。目前,将
RecruiterId
和StatusId
字段保留为空。
字段 值 ConsultantId 2 Email jack.smart@jsfcrudconsultants.com Password jack.smart HourlyRate 75 BillableHourlyRate 110 HireDate 07/22/2008 Resume I'm a great consultant.Hire me - You won't be disappointed! RecruiterId --- StatusId --- - 单击“保存”。当您执行此操作后,将对
StatusId
字段标记一个验证错误。
为什么会出现这种情况?重新检查“咨询机构”数据库的实体关系图。如上面的关系表中所述,CONSULTANT
和CONSULTANT_STATUS
表共享一个不可为 null 的一对多的关系。所以,CONSULTANT
表中的每一个条目都必须包含对CONSULTANT_STATUS
表中条目的引用。这将通过链接这两个表的consultant_fk_consultant_status
外键来表示。可以通过在“服务”窗口中展开一个表的“外键”节点(Ctrl-5 组合键;在 Mac 上为 ⌘-5 组合键)来查看表中保存的外键。
- 要解决验证错误,请从
StatusId
下拉列表中选择entity.ConsultantStatus[statusId=A]
。
注意:RecruiterId
字段可保留为空。正如数据库实体关系图中所示,在CONSULTANT
和RECRUITER
表之间存在一个可为 null 的一对多的关系,这就意味着CONSULTANT
中的条目不需要与一个RECRUITER
条目相关联。 - 单击“保存”。将显示一条消息,表明顾问条目已成功保存。如果单击
Show All Consultant Items
,将看到新条目列在表中。
通常,生成的 Facelets 页会为产生下列问题的用户输入提供出错信息:
- 不可为 null 的表单元格中出现了空字段。
- 对不可更改的数据(例如主键)进行了修改。
- 插入数据的类型不正确。
- 当用户视图与数据库不再同步时对数据进行了修改。
编辑实体类
在前面的子部分中,您看到了 StatusId
下拉列表是如何为您提供不那么容易使用的 entity.ConsultantStatus[statusId=A]
选项。您可能已经注意到:此下拉列表中针对每一项显示的文本都是每个遇到的 ConsultantStatus
实体(即,调用了实体类的 toString()
方法)的字符串表示。
该子部分将演示您可以使用编辑器的代码完成、文档和导航支持作此结论的方式。此外,还教您为下拉列表准备更加易于使用的消息。
- 在编辑器中打开
/consultant/Create.xhtml
文件。这是您刚在浏览器中看到的 "Create New Consultant" 表单。向下滚动到StatusId
下拉列表的代码处(如下面粗体所示)。<h:outputLabel value="#{bundle.CreateConsultantLabel_resume}" for="resume" /> <h:inputTextarea rows="4" cols="30" id="resume" value="#{consultantController.selected.resume}" title="#{bundle.CreateConsultantTitle_resume}" /> <h:outputLabel value="#{bundle.CreateConsultantLabel_statusId}" for="statusId" /> <h:selectOneMenu id="statusId" value="#{consultantController.selected.statusId}" title="#{bundle.CreateConsultantTitle_statusId}" required="true" requiredMessage="#{bundle.CreateConsultantRequiredMessage_statusId}"> <f:selectItems value="#{consultantStatusController.itemsAvailableSelectOne}"/> </h:selectOneMenu> <h:outputLabel value="#{bundle.CreateConsultantLabel_recruiterId}" for="recruiterId" /> <h:selectOneMenu id="recruiterId" value="#{consultantController.selected.recruiterId}" title="#{bundle.CreateConsultantTitle_recruiterId}" > <f:selectItems value="#{recruiterController.itemsAvailableSelectOne}"/> </h:selectOneMenu> </h:panelGrid>
- 检查应用于
<f:selectItems>
标记的value
。value
属性决定了为下拉列表中每项显示的文本。
在itemsAvailableSelectOne
上按 Ctrl-空格键。编辑器的代码完成表示ConsultantStatusController
的getItemsAvailableSelectOne()
方法返回了SelectItem
对象的数组。 - 按 Ctrl 键(在 Mac 上为 ⌘ 键),然后将鼠标悬停在
itemsAvailableSelectOne
上。形成了一个链接,您可以直接导航至ConsultantStatus
实体源代码中的getItemsAvailableSelectOne()
方法。单击该链接。 - 将光标置于方法签名中的
SelectItem[]
返回值上,然后按 Ctrl-空格键调用文档弹出式窗口。在文档窗口中单击 Web 浏览器 (
正如您所看到的,) 图标,在外部 Web 浏览器中打开 Javadoc。
SelectItem
类属于 JSF 框架。文档中提到的UISelectOne
组件使用您在上述步骤 1 中检查的标记中的<h:selectOneMenu>
标记来表示。 - 按 Ctrl 键(在 Mac 上为 ⌘ 键),然后将鼠标悬停在
findAll()
上。随即出现一个弹出式窗口,显示方法签名。
可以看到此处的ejbFacade.findAll()
返回了ConsultantStatus
对象的List
。 - 导航至
JsfUtil.getSelectItems
。将鼠标悬停在getSelectItems
上并按 Ctrl 键(在 Mac 上为 ⌘),然后单击显示的链接。
注意:回想一下,JsfUtil
是在您完成“通过实体类创建 JSF 页”向导时生成的一个实用程序类。
该方法对实体列表(即ConsultantStatus
对象的List
)执行循环操作,为每个实体创建SelectItem
。如下面粗体所示,每个SelectItem
都是使用实体对象和对象的标签来创建的。public static SelectItem[] getSelectItems(List<?> entities, boolean selectOne) { int size = selectOne ? entities.size() + 1 : entities.size(); SelectItem[] items = new SelectItem[size]; int i = 0; if (selectOne) { items[0] = new SelectItem("", "---"); i++; } for (Object x : entities) { items[i++] = new SelectItem(x, x.toString()); } return items; }
该标签使用实体的toString()
方法来创建,并且在响应中呈现对象时是对象的表示。(请参见SelectItem(java.lang.Object value, java.lang.String label)
构造函数的 Javadoc 定义。)
既然您已在查看下拉列表中的项时,验证了实体toString()
方法正是浏览器中所呈现的内容,那么请修改ConsultantStatus
toString()
方法。 - 在编辑器中打开
ConsultantStatus
实体类。修改toString
方法以返回statusId
和description
。这些是对应于CONSULTANT_STATUS
表的两列的实体属性。public String toString() { return statusId + ", " + description; }
- 重新运行该项目。当浏览器显示欢迎页面时,单击
Show All Consultant Items
链接,然后单击Create New Consultant
。
检查StatusId
下拉列表。将看到现在显示的是数据库的CONSULTANT_STATUS
表中所包含的一个记录的状态 ID 和描述。
转载于:https://blog.51cto.com/qyweiyy/760834