【发布时间】:2023-03-21 08:37:01
【问题描述】:
我在 JSF 2.1 + Primefaces 5.1 中有一个网络应用程序。我有一个带有可选行的数据表。当我选择一行并按下编辑按钮时,会打开一个对话框,允许用户编辑该记录的值。当用户按下对话框的保存按钮时,将调用一个过程来更新行并通过 Ajax 更新数据表。如果该过程由于某些业务逻辑要求而失败,则数据表不应更新,它应保留该行的旧值。但是发生的情况是这些值在客户端得到更新,尽管在数据库中它们仍然使用旧的(和正确的)值。刷新后,数据表会显示旧值。
数据表和编辑按钮:
<h:form id="search_users_form_id">
<p:commandButton id="edit_user_button_id" value="#{msgs.edit}" disabled="#{usersBean.editUserButtonDisabled}" onclick="openDialog('edit_user_dlg')" update=":edit_user_form_id" actionListener="#{usersBean.populateDataForUserEdition}"/>
<p:dataTable id="users_table_id" var="user" value="#{usersBean.users}" rowKey="#{user.id}" paginator="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15" selection="#{usersBean.selectedUser}" selectionMode="single" emptyMessage="#{msgs.no_records}" sortBy="#{user.id}"
sortOrder="ascending" rows="15">
<f:facet name="header">
#{msgs.users}
</f:facet>
<p:ajax event="rowSelect" listener="#{usersBean.onRowSelect}" update=":search_users_form_id:edit_user_button_id"/>
<p:ajax event="rowUnselect" listener="#{usersBean.onRowUnselect}" update=":search_users_form_id:edit_user_button_id"/>
<p:column headerText="#{msgs.id}" sortBy="#{user.id}" styleClass="centered-column">
#{user.id}
</p:column>
<p:column headerText="#{msgs.description}" sortBy="#{user.description}" styleClass="centered-column">
#{user.description}
</p:column>
<p:column headerText="#{msgs.password}" sortBy="#{user.password}" styleClass="centered-column">
#{user.password}
</p:column>
<p:column headerText="#{msgs.sending_system}" sortBy="#{user.playerIn.description}" styleClass="centered-column">
#{user.playerIn.description}
</p:column>
<p:column headerText="#{msgs.receiving_system}" sortBy="#{user.playerOut.description}" styleClass="centered-column">
#{user.playerOut.description}
</p:column>
<p:column headerText="#{msgs.active}" sortBy="#{user.active}" styleClass="centered-column">
<p:selectBooleanCheckbox value="#{user.active}" disabled="true"/>
</p:column>
<f:facet name="footer">
</f:facet>
</p:dataTable>
</h:form>
对话框:
<p:dialog modal="true" appendTo="@(body)" header="#{msgs.edit_user}" widgetVar="edit_user_dlg" closeOnEscape="true" resizable="false">
<h:form id="edit_user_form_id">
<h:panelGrid columns="3">
#{msgs.description}: <p:inputText value="#{usersBean.selectedUser.description}"/>
<h:panelGroup layout="block">
<p:graphicImage id="edit_user_description_tooltip_image_id" library="images" name="icon-tooltip.jpg"/>
<p:tooltip id="edit_user_description_tooltip_id" for="edit_user_description_tooltip_image_id" value="#{msgs.tooltip_users_description}"/>
</h:panelGroup>
#{msgs.password}:
<p:inputText value="#{usersBean.selectedUser.password}" maxlength="50"/>
<h:panelGroup layout="block">
<p:graphicImage id="edit_user_password_tooltip_image_id" library="images" name="icon-tooltip.jpg"/>
<p:tooltip id="edit_user_password_tooltip_id" for="edit_user_password_tooltip_image_id" value="#{msgs.tooltip_users_password}"/>
</h:panelGroup>
#{msgs.sending_system}:
<p:selectOneMenu styleClass="edit-user-selectonemenu" id="user_sending_system_id" value="#{usersBean.selectedUser.playerIn}" effectSpeed="fast" filter="true" filterMatchMode="contains" converter="#{playerConverter}">
<f:selectItem itemLabel="#{msgs.select_option}" itemValue="#{null}" noSelectionOption="true"/>
<f:selectItems value="#{usersBean.players}" var="player" itemValue="#{player}" itemLabel="#{player.description}"/>
</p:selectOneMenu>
<h:panelGroup layout="block">
<p:graphicImage id="edit_user_sending_system_tooltip_image_id" library="images" name="icon-tooltip.jpg"/>
<p:tooltip id="edit_user_sending_system_tooltip_id" for="edit_user_sending_system_tooltip_image_id" value="#{msgs.tooltip_users_sending_system}"/>
</h:panelGroup>
#{msgs.receiving_system}:
<p:selectOneMenu styleClass="edit-user-selectonemenu" id="user_receiving_system_id" value="#{usersBean.selectedUser.playerOut}" effectSpeed="fast" filter="true" filterMatchMode="contains" converter="#{playerConverter}">
<f:selectItem itemLabel="#{msgs.select_option}" itemValue="#{null}" noSelectionOption="true"/>
<f:selectItems value="#{usersBean.players}" var="player" itemValue="#{player}" itemLabel="#{player.description}"/>
</p:selectOneMenu>
<h:panelGroup layout="block">
<p:graphicImage id="edit_user_receiving_system_tooltip_image_id" library="images" name="icon-tooltip.jpg"/>
<p:tooltip id="edit_user_receiving_system_tooltip_id" for="edit_user_receiving_system_tooltip_image_id" value="#{msgs.tooltip_users_receiving_system}"/>
</h:panelGroup>
#{msgs.active}: <p:selectBooleanCheckbox id="edit_user_active_id" value="#{usersBean.selectedUser.active}"/>
<h:panelGroup layout="block">
<p:graphicImage id="edit_user_active_tooltip_image_id" library="images" name="icon-tooltip.jpg"/>
<p:tooltip id="edit_user_active_tooltip_id" for="edit_user_active_tooltip_image_id" value="#{msgs.tooltip_users_active}"/>
</h:panelGroup>
</h:panelGrid>
<h:panelGroup styleClass="edit-user-main-tooltip" layout="block">
<p:graphicImage id="edit_user_main_tooltip_image_id" library="images" name="icon-tooltip.jpg"/>
<p:tooltip id="edit_user_main_tooltip_id" for="edit_user_main_tooltip_image_id" value="#{msgs.tooltip_users_edit}"/>
</h:panelGroup>
<h:panelGroup styleClass="edit-user-dialog-buttons" layout="block">
<p:commandButton id="edit_user_save_button_id" value="#{msgs.save}" action="#{usersBean.updateUser}" onclick="closeDialog('edit_user_dlg')" update=":search_users_form_id:users_table_id"/>
<p:commandButton id="edit_user_cancel_button_id" value="#{msgs.cancel}" type="button" onclick="closeDialog('edit_user_dlg')"/>
</h:panelGroup>
</h:form>
</p:dialog>
update 方法只获取selectedUser 对象并将其传递给存储过程。
public void updateUser() {
logger.entry();
this.selectedUser.setPlayerInId(this.selectedUser.getPlayerIn().getId());
this.selectedUser.setPlayerOutId(this.selectedUser.getPlayerOut().getId());
this.updateUser(this.selectedUser);
this.clearData();
logger.exit();
}
public void updateUser(DtoUser dtoUser) {
try {
logger.entry(dtoUser);
DtoBoUsers dtoBoUsers = dtoUser.toDtoBoUsers();
DtoTypeGenericResponse genericResponse = usersService.updateUser(backofficeUserBean.getCurrentSessionId(), dtoBoUsers);
if (genericResponse.getVResponse().equals(startupBean.getProperty(BackofficeProperties.RESPONSE_NOK))) {
BigDecimal id = this.selectedUser.getId();
logger.info(this.users.get(id.intValue()-1));
} else {
}
logger.exit(dtoUser);
} catch (BackofficeException | RuntimeException e) {
logger.error(ExceptionUtils.getStackTrace(e.fillInStackTrace()));
}
}
我该如何解决这个问题?我是否必须通过对数据库的查询再次强制重新填充数据表?还是我有更清洁的方法?
【问题讨论】:
-
答案取决于您在明显停留在同一页面时检测到服务方法失败的准确程度。我希望在 bean 操作方法中看到一个 try-catch,所以你可以在 catch 中处理它,但这甚至不存在。
-
DB 过程根据验证结果返回“OK”或“NOK”。我已经用调用它的方法更新了初始帖子。
-
如果对话框失败,您真的要关闭对话框吗?也许像
oncomplete="if (args.validationFailed) closeDialog('edit_user_dlg')"这样的东西会更好。 -
我想我还得写点别的。我试过
RequestContext.getCurrentInstance().addCallbackParam("validationFailed", true);,但没用。 -
我还将
addCallbackParam调用替换为FacesContext.getCurrentInstance().validationFailed();。在 Primefaces 的用户指南 (11.1) 上,据说“默认情况下,如果验证失败,则会隐式添加 validationFailed 回调参数。”
标签: jsf jsf-2 primefaces datatable