避免在记录编辑期间发生错误时更新数据表(JSF + Primefaces)

Avoid datatable update in case of error during record edition (JSF + Primefaces)

我在 JSF 2.1 + Primefaces 5.1 中有一个 Web 应用程序。我有一个包含 select 行的数据表。当我 select 一行并按下编辑按钮时,将打开一个对话框以允许用户编辑该记录的值。当用户按下对话框的保存按钮时,将调用一个过程来更新行并通过 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>

更新方法只获取 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()));           
        } 
    }

我该如何解决这个问题?我是否必须通过对数据库的查询强制重新填充数据表?或者我有更简洁的方法吗?

您基本上只想在业务服务调用成功后才执行update=":search_users_form_id:users_table_id"。您可以通过从 <p:commandButton> 中删除该属性并在 RequestContext#update().

的帮助下在操作方法中以编程方式执行它来实现。
try {
    // ...
    RequestContext.getCurrentInstance().update("search_users_form_id:users_table_id");
}
catch (Exception e) {
    // ...
}