Primefaces数据表排序列表

时间:2012-12-20 15:51:30

标签: java primefaces

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

和myService:

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提供的内容并不满意..设计相当不错,但功能上存在很多错误。我与其他组件有类似的问题,我发现了一些肮脏的修复,但它让我感到困扰的是复杂性超过简单性。

1 个答案:

答案 0 :(得分:0)

一边编辑,

这里的问题是每次对实体进行排序时都会刷新列表。由于每次在排序后刷新UI时都会设置框架,因此您需要提取新列表。

基本上你看到了 - &gt; (这不准确是它正在做什么的草图)

  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实现)维护引用(有状态),因此您需要一个低内存解决方案。

它可能看起来像 - &gt;

@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天不会那么多工作。)