当前位置: 首页 > 知识库问答 >
问题:

Primefaces数据表按列表排序

於炯
2023-03-14

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

和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 sessionScoped,这不是很好的方法,因为我占用了服务器的内存加载我的对象并在整个会话中保持它们处于活动状态,除此之外,保持列表更新的开销要大得多,因为每当我向视图发出请求时,我都必须手动执行此操作。当在带注释的方法中对该页面发出第一个请求时,将提取@PostConstruct列表。之后我需要保持最新状态。
我需要知道是否有任何其他方法可以直接从数据库获取列表并将其提供给primefaces而不是将其保留在bean中?到目前为止,我对Primefaces提供的东西并不满意。设计非常好,但功能中有很多错误。我对其中的其他组件也有类似的问题,我发现了肮脏的修复程序,但它困扰着我的复杂性而不是简单性。

共有1个答案

那开济
2023-03-14

撇开编辑不谈,

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

基本上你看到的是-

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

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

解决方案是使用您可以在排序后引用的成员。这不是一个大问题,因为您可以使用查看范围而不是会话或请求范围。从内存角度来看,您考虑它是对的,但您可能会过度优化,因为您正在失去功能。

简而言之,修复是 -

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

因为您现在可以对列表进行排序并维护组件将工作的引用。如果您真的遇到内存问题,那么您可以开始沿着优化的道路前进,即在服务端执行排序,创建一个根据调用和返回而不是请求范围进行排序的新列表。Primeface允许您这样做,但请先尝试简单的方法。

-----------作为对挑剔的回应(因为我今天有时间,而且很有趣......)--------/

我不想对你有敌意。如果您处于这种规模,为什么不实现一个自定义组件来根据您的内存负载处理它呢?显然,在实体和数据库本身之间有一个抽象,所以实现自定义排序,这样您的< code>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)才能看到你的选择是什么。此外,它是开源的,因此您可以简单地扩展表以使用侦听器作为选项,而不是指向集合的简单链接。

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

 类似资料:
  • 当xhtml运行时,数据表会显示出来,但只有一列显示为可用于排序(即,标题中有向上/向下箭头图标)。 dataTable有两个问题: 只有一列(年份)显示为可用于排序。(Year是Car类中“int”类型的属性,而其他三列是String类型,因此问题的一个方面是String字段忽略了sortby=“#{Car.xxx}”标记。) 年份列实际上是不可排序的。点击年份标题的向上/向下箭头没有效果。当点

  • 该页显示列表中的正确值。然而,当我尝试选择一个项目。它不起作用。 我能在列表中选择一个项目吗?

  • 我使用的是PrimeFaces 2.2和JSF 2.0.3。 我有一个包含以下数据表的xhtml视图: ..具有以下背衬豆: 注意母亲姓名列上的“commandLink”和出生日期列上的“sortBy”。 我遇到了一个奇怪的问题,似乎仅限于IE,如果我按DOB对数据进行排序,然后分页到最后一页并单击表中最后一条记录的commandLink,它会触发两个action事件。第一个事件正确地报告了我单击

  • 我有一个p:dataTable,它存储已处理表单的结果,我执行以下操作: 填充表单值。 提交。 已填充数据表--对任何列进行筛选。 更改表单值。 提交。 使用新结果填充数据表。 对任意列排序--将显示来自#3的筛选结果。 我有一个用于筛选值的arraylist,但我没有在bean中对它做任何操作。提交时,我调用actionListener,该actionListener将dataTable强制转换

  • 问题内容: 我有一个数字列表:(这是现有记录的ID) 我有一个带有列和的mysql表,其中是整数主键。我想从该表中选择的记录,但在一个特定的顺序,例如,,,,,。 是否可以在MyISAM的查询中执行此操作,而无需任何后处理? 最简单的方法是什么? 问题答案: 由于,一个简单就足够了。 但是,如果您要这样订购:,则可以使用function : 如果查询匹配的行多于您列出的行 返回时,行不匹配任何您列

  • 我用的是Primefaces 5.2。 到目前为止,排序工作还不错,但如果我对其中一个表(我们称之为表a)进行排序,然后刷新页面(例如,通过激发h:commandButton),则会出现奇怪的行为,最后会出现NullPointerException。在这种情况下,所有表都有与表a相同的列高亮显示。此外,当我随后对表a以外的表进行排序时,就会出现以下异常: