既然您的项目已包含了实体类、用于控制实体类的 EJB 会话 Bean 和 JSF 驱动的用于显示和修改数据库的前端,那么请尝试运行该项目以查看结果。
以下是一系列可选的小练习,可用来进一步熟悉应用程序,以及 IDE 所提供的功能。
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
) 和销毁单个表记录的数据。
运行提供的脚本,该脚本会生成数据库表的样例数据。脚本 (mysql_insert_data_consult.sql
) 包含在咨询机构数据库 zip 文件中,该文件可从所需软件表中下载。
根据所使用的数据库服务器(MySQL 或 JavaDB),您可以运行提供的脚本,该脚本会为数据库表生成样例数据。对于 MySQL,该脚本为mysql_insert_data_consult.sql
。对于 JavaDB,该脚本为 javadb_insert_data_consult.sql
。两个脚本分别包含在各自的归档文件中,可以通过所需软件表进行下载。
consult
数据库。 consult
数据库中包含的新数据所必需的步骤。为此,请单击“输出”窗口中的 GlassFish 服务器标签(GlassFish 服务器标签显示服务器日志),然后单击左旁注中的“重新启动服务器”(Show All Consultant Items
" 链接。将看到该列表不再为空。 可以使用 IDE 的数据库表查看器来显示和修改直接在数据库中维护的表数据。例如,右键单击“服务”窗口中的 consultant
表,然后选择“查看数据”。
在编辑器的顶部将显示用于执行操作的 SQL 查询,下面则显示表的图形视图。
在表单元格内双击以对数据进行内联修改。单击“提交记录”() 图标以将更改提交到数据库。
图形视图提供了更多的功能。有关详细信息,请参见 NetBeans IDE 6.5 中数据库支持的改进。
/consultant/List.xhtml
页。第 8 行表明该页的呈现依赖于 Facelets template.xhtml
文件。 <ui:composition template="/template.xhtml">
要显示行号,请右键单击编辑器的左旁注,然后选择“显示行号”。
template.xhtml
。按 Alt-Shift-O 组合键(在 Mac 上为 Ctrl-Shift-O 组合键),然后开始键入 template
。 <ui:insert>
标记将其他文件的内容插入到其标题和正文中。将光标置于 <ui:insert>
标记上,然后按 Ctrl-空格键调用文档弹出式窗口。 List.xhtml
文件(按 Ctrl-Tab 组合键)。<ui:define>
标记用来定义将应用于模板标题和正文的内容。为每个实体类生成的所有 4 个 Facelets 文件(Create.xhtml
、Edit.xhtml
、List.xhtml
和 View.xhtml
)都使用了此模式。Bundle.properties
文件中的本地化消息)上。按 Ctrl-空格键查看本地化消息。 List
",该表达式将应用到模板标题,并且可以从呈现在浏览器中的页面得到验证。Create New Consultant
链接的代码(第 92 行)。如下所示: <h:commandLink action="#{consultantController.prepareCreate}" value="#{bundle.ListConsultantCreateLink}"/>
commandLink
的 action
属性上按 Ctrl-空格键以调用文档弹出式窗口。 action
属性表示在浏览器中单击链接时处理请求的方法。将提供以下文档: action
值通常是指 JSF 受管 Bean 中的一个方法,其值为 String
。然后 JSF 的 NavigationHandler
会使用该字符串将请求转发到相应的视图中。可通过以下步骤来验证这一点。consultantController
上,然后按 Ctrl-空格键。编辑器的代码完成表明 consultantController
是一个 JSF 受管 Bean。 prepareCreate
,然后按 Ctrl-空格键。代码完成列出了包含在 ConsultantController
受管 Bean 中的方法。 prepareCreate
上。形成了一个链接,您可以直接导航至 ConsultantController
受管 Bean 中的prepareCreate()
方法。 prepareCreate()
方法(如下所示)。 public String prepareCreate() { current = new Consultant(); selectedItemIndex = -1; return "Create"; }该方法将返回
Create
。NavigationHandler
在后台收集信息,并将 Create
字符串应用于以视图(为响应请求而发送)为目标的路径:/consultant/Create.xhtml
。(在 JSF 2.0 中,由于隐式导航所以文件扩展名是推断出来的。)Create New Consultant
" 链接。正如之前子部分中的说明,此操作将触发呈现 /consultant/Create.xhtml
页。RecruiterId
和 StatusId
字段保留为空。 字段 | 值 |
---|---|
ConsultantId | 2 |
[email protected] | |
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 页会为产生下列问题的用户输入提供出错信息:
在前面的子部分中,您看到了 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
对象的数组。 itemsAvailableSelectOne
上。形成了一个链接,您可以直接导航至 ConsultantStatus
实体源代码中的 getItemsAvailableSelectOne()
方法。单击该链接。SelectItem[]
返回值上,然后按 Ctrl-空格键调用文档弹出式窗口。 在文档窗口中单击 Web 浏览器 () 图标,在外部 Web 浏览器中打开 Javadoc。
SelectItem
类属于 JSF 框架。文档中提到的 UISelectOne
组件使用您在上述步骤 1 中检查的标记中的 <h:selectOneMenu>
标记来表示。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 和描述。