0

我开始在我的项目中使用 primefaces,我马上就遇到了问题。我列出了一些我使用实体管理器从数据库中获取的东西,并将其呈现在 primefaces 数据表的视图中。在我的支持 bean 中,我有: List getList() 在其中我使用实体管理器从数据库中检索记录并立即返回..

和我的服务:

public List<MyEntity> getDataList(){
  return entityManager.createNamedQuery("MyEntity.getAll").getResultList();
}

我的豆子:

public List<MyEntity> getList(){
  return myService.getDataList();
}

风景:

<p:dataTable var="myEntityInstance" value="#{myBean.list}"...

这种方式primefaces排序不起作用,我在堆栈上的某个地方读到该列表需要成为我的支持bean的成员,我认为这很奇怪..这迫使我保持​​我的bean sessionScoped,因为我占用了这个不是很好的方法服务器的内存加载我的对象并在整个会话期间保持它们处于活动状态,除此之外,保持列表更新的开销要大得多,因为每当我向视图发出请求时,我都必须手动进行。当在 @PostConstruct 注释方法中对该页面的第一个请求发出时,我的列表被获取。之后我需要保持它是最新的。
我需要知道是否有任何其他方法可以直接从数据库中获取列表并将其提供给 primefaces 而不是将其保存在 bean 中?到目前为止,我对 primefaces 提供的功能并不满意。设计非常好,但功能中有很多错误。我对其中的其他组件也有类似的问题,我发现了一些肮脏的修复,但这让我感到复杂而不是简单。

4

1 回答 1

0

抛开编辑,

这里的问题是您的列表在每次排序时都会从实体中刷新。由于每次在排序后刷新 UI 时设置框架的方式,您将拉出一个新列表。

基本上你看到了->(这不准确,它是它正在做的事情的草图)

  UI -> sort(myBean.getList());
  UI -> redraw(myBean.getList());

看这意味着您有两个不同的引用,您对引用 #1 进行排序,然后丢弃它并获取新的渲染引用。因此,您的排序不起作用。

解决方案是使用排序后可以引用的成员。这不是一个大问题,因为您可以使用 View Scope 而不是 Session 或 Request 范围。内存方面,你的想法是对的,但你可能过度优化,因为你正在失去功能。

简而言之,修复是->

@ViewScoped
public class MyBean
{
  private List<T> myList;
  public List<T> getMyList()
  {
    if(myList != null)
      return myList;
    myList = Service.getMyList();
    return myList;
  }
}

因为您现在可以对列表进行排序并维护引用,所以该组件将起作用。如果您确实遇到了内存问题,那么您可以开始沿着优化路径走下去,即在服务端执行排序,创建一个基于调用排序的新列表,然后在请求范围内返回。Primefaces 允许您这样做,但请先尝试简单的方法。

//-----------回应吹毛求疵(因为我今天有时间,很有趣……)--------/

我不是想对你怀有敌意。如果您处于那种规模,为什么不实现一个自定义组件来根据您的内存负载来处理它?显然,实体和数据库本身之间存在抽象,因此请实现自定义排序,以便您的getData()方法能够返回正确的排序集,而不是维护的引用。显然 Primefaces(和大多数 JSF 实现)维护引用(有状态),因此您需要一个低内存解决方案。

它可能看起来像 ->

@RequestScoped
public class LessMemoryBean
{
  public List<T> getList()
  {
    StatefulBean state = getStatefulBean();
    //Some switch/case or other method of determining state
    return service.getSortedList(state.getState()); //I like hashmaps, but anything could work.
  }
}

@ViewScoped
public class StatefulBean
{
  private HashMap<String, Boolean> state;
  public void sortField(String key, boolean sortBy)
  {
    state.put(key, sortBy); //Construct the proper query via the keys provided
  }
}

//XHTML
<p:dataTable value="#{lessMemoryBean.data}">
  <!-- Whatever you need -->
  <p:column>
    <f:facet name="header">
      <p:commandButton 
        //Do whatever control method you want for sorting and setting booleans
      />
    </f:facet>
  </p:column>
....

因为您使用的是对 RequestScoped bean 的引用,并且该 bean 引用了 ViewScoped,所以您的列表存储在请求中(尽快处理),但表的状态是分开的。显然,这不是开箱即用的,Primefaces 支持一些听众,但您需要更深入地挖掘 (RTFM) 以查看您的选择。此外,它是开源的,因此您可以简单地扩展表以使用侦听器作为选项,而不是简单的链接到Collection.

你说的是优化,在我看来,这意味着你需要做很多额外的工作。有它(我个人会使用标准数据表或在这种情况下实现我自己的复合组件。最多 1-2 天不会有那么多工作)。

于 2012-12-20T19:01:57.500 回答