Java Primefaces数据表列表排序

Java Primefaces数据表列表排序,java,primefaces,Java,Primefaces,我开始在我的项目中使用primefaces,我马上就遇到了问题。我用entity manager从db中获取了一些东西,并将其显示在primefaces数据表的视图中。在我的支持bean中,我有:List getList(),在这里,我使用实体管理器从数据库中检索记录并立即返回 和我的服务: public List<MyEntity> getDataList(){ return entityManager.createNamedQuery("MyEntity.getAll").g

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

和我的服务:

public List<MyEntity> getDataList(){
  return entityManager.createNamedQuery("MyEntity.getAll").getResultList();
}
public List getDataList(){
返回entityManager.createNamedQuery(“MyEntity.getAll”).getResultList();
}
我的豆豆:

public List<MyEntity> getList(){
  return myService.getDataList();
}
public List getList(){
返回myService.getDataList();
}
观点:

<p:dataTable var="myEntityInstance" value="#{myBean.list}"...
把编辑放在一边

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

基本上你看到的是->(这并不准确,它只是一个它正在做什么的草图)

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

解决方案是使用排序后可以引用的成员。这不是一个大问题,因为您可以使用视图范围而不是会话或请求范围。就内存而言,您的想法是对的,但您可能在失去功能的同时过度优化了

简而言之,解决方案是->

@ViewScoped
public class MyBean
{
  private List<T> myList;
  public List<T> getMyList()
  {
    if(myList != null)
      return myList;
    myList = Service.getMyList();
    return myList;
  }
}
因为您使用的是对RequestScoped bean的引用,而该bean引用的是ViewScoped,所以您的列表存储在请求中(尽快释放),但表的状态是分开的。显然,这不是现成的,Primefaces支持一些侦听器,但您需要深入挖掘(RTFM)以了解您的选项。此外,它是开源的,因此您可以简单地扩展表,将侦听器用作选项,而不是指向
集合的简单链接


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

@Bhavik:编辑得太差了。这篇文章还有很多有待改进的地方。谢谢你为我解释这一切。我还有一个问题。。为什么prime不能只获取列表引用,对其进行排序并使用相同的引用传递给绘图方法。。prime试图再次从bean中获取列表并将其绘制在排序上,这让我有点困惑。。我从方法返回的引用匿名地存在于内存中,prime可以为其操作引用相同的引用;UI:排序(theList);UI:绘制(列表);我认为这是一个简单可行的算法。这将允许我使用请求范围的bean并使排序工作。正如我现在所理解的,prime要求我为他的行为保留一个列表引用,并且他严格依赖me方法来获取相同的列表。这个我不喜欢,我不知道它的工作原理是什么,但我只是不喜欢它=)喜欢与否,这就是实现。它必须在某处存储对列表的引用,这意味着它要么由bean管理,要么由框架管理。对我来说,这似乎是正确的实现。它很简单,很容易管理范围,并且允许使用最少的代码来实现一些非常强大的功能。可以这样想:如果您的请求数据超出了请求的范围,那么它就不是请求范围了,是吗?我不希望我的数据超出范围,因为prime的排序功能会这样做。我希望每次提出请求时都能从数据库中提取项目,并以排序的方式呈现它们。如果我使用JPA的标准和两个CommandLink,根据点击的内容进行动态查询(最后我可能会选择这个),我可以做到这一点,但我从prime开始,所以我要求用其他方法来进行排序。如果我有1000个项目,平均有1000个用户,会怎么样。假设列表中的一个对象占用100B,即1000^2*100B~97656.25MB~97GB。。这说明了低可扩展性和内存占用。这是我在服务器上需要的大量RAM,以保持我的应用程序运行和容纳1000个用户会话。。想想看,我可能还保留了其他清单,其中可能有很多项目。。这显然不是我的好办法。。这就是为什么db首先存在的原因,不仅仅是为了永久存储东西,而是为了释放服务器内存占用(证明我错了)。
@ViewScoped
public class MyBean
{
  private List<T> myList;
  public List<T> getMyList()
  {
    if(myList != null)
      return myList;
    myList = Service.getMyList();
    return myList;
  }
}
@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>
....