【问题标题】:Why the jsf view is not updated after new data in the backing bean are loaded from database?为什么从数据库加载后备 bean 中的新数据后 jsf 视图没有更新?
【发布时间】:2010-10-18 12:49:05
【问题描述】:

我 - 不幸的是 - 与 jsf 合作,我遇到了问题。 我有一个 jsf 页面,它使用 <h:dataTable> 组件显示包含一些数据的表格。 此表的每一行都有一个 <h:commandLink> 和一个删除操作以删除该行中的项目。 当我执行该操作时,支持 bean 中的方法被正确调用,包含表项的 ArrayList 被正确更新,并且导航方法返回到表所在的同一页面,正确执行。

但是当页面重新加载时,表格不会更新。我看到删除操作之前表格中的相同项目。

如果我再次重新加载页面,现在表格已更新。

看起来就像是在后台 bean 完成更新之前渲染了视图。

如何在支持 bean 完成更新后强制呈现视图?

这里有一些代码:

jsf页面中的commandLink,dataTable里面:

<h:column>
<f:facet name="header">
    <h:outputText value="Rimuovi" />
</f:facet>
<h:commandLink action="#{servicesListBean.removeServizio}" title="Rimuovi questo servizio" onclick="if(!confirm('Vuoi davvero rimuovere questo servizio?')) return false">
    <h:outputText value="Rimuovi" />
</h:commandLink>
</h:column>

这里是backing bean中的方法:

public String removeServizio() {
        this.servizioToRemove = (Servizio) getDataTable().getRowData();
        try {
        ServiziDAO.removeServizio(this.servizioToRemove.getId());
        } catch (Exception e) {
            // ...
        }

        return userSessionBean.goToElencoServizi(); 
    }

在这种情况下,我将 请求范围 给了支持 bean。 我已经尝试给它会话范围并调用一个方法来更新列表,但结果是一样的。

我希望我已经足够清楚了。提前感谢大家。


对这个改变一切的问题的更新

感谢大家。 正如 McDowell 所说,问题不在渲染视图的时间,问题根本与 JSF 无关。

发生的情况是,当我从数据库中删除一个项目时,我没有删除该行,我只是为该项目设置了一个结束日期。这是在我的应用程序中执行此操作的正确方法,但是在将结束日期设置为项目的查询中,我花时间使用System.currentTimiMillis(),在重新加载更新列表的查询中,我使用了sysdate甲骨文服务器。

这两个日期之间有几分之一秒的差异,这就是为什么我在重新加载页面时可以看到更新的列表:因为已经过了一到两秒!

也许这个问题对其他人有用。

【问题讨论】:

    标签: java jsf jakarta-ee


    【解决方案1】:

    看起来就像视图一样 在此之前渲染 backing bean 已完成更新。

    发生这种情况的唯一方法是,如果您在另一个线程中完成工作 - 但看起来您并没有这样做。

    我猜,但这看起来像是您的支持 bean 中的逻辑问题。您的 servicesListBean 是否保持状态?那就是:

    1. HTTP POST
    2. 生命周期的 RESTORE VIEW 阶段导致在请求范围内创建 servicesListBean(生命周期的每个阶段都需要遍历每一行)
    3. servicesListBean 从持久存储中获取行并将它们缓存在 bean 状态中
    4. 当我们进入 INVOKE APPLICATION 阶段时,removeServizio() 从持久性存储中删除目标行,但不对缓存的 bean 状态做任何事情李>
    5. RENDER RESPONSE 阶段呈现陈旧的缓存 bean 状态
    6. 如果您现在刷新,bean 会使用新的缓存值重新创建,并且您会看到正确的状态

    这个支持 bean 重现了问题:

    public class DeleteFromRowBean {
    
      private ListDataModel dataModel;
    
      public DataModel getList() {
        if (dataModel == null) {
          List<RowBean> list = PersistenceStore.fetch();
          dataModel = new ListDataModel(list);
        }
        return dataModel;
      }
    
      public String deleteCurrentRow() {
        if (dataModel == null) {
          throw new IllegalStateException();
        }
        RowBean row = (RowBean) dataModel.getRowData();
        PersistenceStore.delete(row.getId());
        return null; // no navigation required
      }
    
    }
    

    在数据表迭代时修改列表不是一个好主意(您会得到并发修改异常)。我的示例 bean 中最简单的解决方案就是释放对缓存数据的引用。在 INVOKE APPLICATION 阶段的迭代期间,数据表已经有对此的引用;当 RENDER RESPONSE 启动时,数据表将再次调用 getList(),从而从持久存储中获取新状态。

    public class DeleteFromRowBean {
    
      private ListDataModel dataModel;
    
      public DataModel getList() {
        if (dataModel == null) {
          List<RowBean> list = PersistenceStore.fetch();
          dataModel = new ListDataModel(list);
        }
        return dataModel;
      }
    
      public String deleteCurrentRow() {
        if (dataModel == null) {
          throw new IllegalStateException();
        }
        RowBean row = (RowBean) dataModel.getRowData();
        PersistenceStore.delete(row.getId());
        // flush cached data
        dataModel = null;
        return null; // no navigation required
      }
    
    }
    

    【讨论】:

      【解决方案2】:

      如果您没有明确重定向到“另一个”页面(即使它是同一页面),您将获得旧数据。是特色。尝试类似:

      public String removeServizio() {
          .
          .
          .
          userSessionBean.goToElencoServizi(); // if this redirects to needed page
          return null;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-11
        • 2015-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多