为什么在从数据库加载辅助bean中的新数据后不更新jsf视图?

时间:2009-04-09 10:40:46

标签: java jsf java-ee

我 - 不幸的是 - 与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>

这里是支持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()占用了时间,在重新加载上传列表的查询中我使用了{{1 Oracle服务器。

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

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

2 个答案:

答案 0 :(得分:4)

  

看起来就像观点一样   在那之前渲染了支持bean   已完成更新。

这种情况发生的唯一方法就是如果你在另一个线程中完成了工作 - 但看起来你不是这样做的。

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

  1. HTTP POST
  2. 生命周期的 RESTORE VIEW 阶段会导致在请求范围内创建 servicesListBean (生命周期的每个阶段都需要迭代每一行)
  3. servicesListBean 从持久性存储中获取行,并以bean状态缓存它们
  4. 当我们进入 INVOKE APPLICATION 阶段时, removeServizio()会从持久性存储中删除目标行,但不会对缓存的bean状态执行任何操作
  5. RENDER RESPONSE 阶段呈现陈旧的缓存bean状态
  6. 如果您现在刷新,则会使用新的缓存值重新创建bean,并且您会看到正确的状态
  7. 这个支持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
      }
    
    }
    

答案 1 :(得分:1)

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

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