【发布时间】:2015-07-02 14:15:36
【问题描述】:
我正在尝试使用 LazyDataModel 向 <p:dataScroller> 提供未知数量的项目。我根据请求(来自用户交互)从存储中读取它们,然后将所需数量发送回模型。
项目确实有尽头,但直到我都读完才知道数量,所以我在 DataModel 上设置了 1,000 个项目的上限。
Model中load()的实现:
@Override
public List<MyPojo> load(int first, int pageSize, String sortField,
SortOrder sortOrder,
Map<String, Object> filters) {
return managedBean.loadMoreItens(first, pageSize);
}
还有loadMoreItens(int, int):
List<MyPojo> loadMoreItens(int first, int pageSize) {
int amountLoaded = 0;
while(first+pageSize > this.list.size()) {
if (this.endReached) {
break;
}
amountLoaded++;
list.add(readNewItem()); //readNewItem sets boolean if it reaches the end.
}
int end = first + pageSize;
// do some other unrelated stuff like logging and such.
return list.subList(first, Math.min(end, list.size()));
}
它工作正常,每次用户滚动组件时都会加载chunkSize itens(所以我将跳过在这里发布 JSF),但是当到达终点时,会抛出一个讨厌的异常:
Jul 02, 2015 10:58:51 AM com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback visit
SEVERE: java.lang.IllegalArgumentException: fromIndex(380) > toIndex(371)
这里的380 / 371数字是随机生成的测试质量,所以数量可能会发生变化。问题是要读取的项目已到末尾,但模型仍然认为少于 1,000 个。
如何避免抛出该异常?
PS:
- 项目并非来自数据库。如果不获取所有物品,就无法进行“轻量查询”来了解数量。
- 获取新物品的过程非常昂贵(无法分辨它们是什么),除非需要,否则不应这样做。
- managedBean 使用前 20 个项目进行初始化,这在需求规范中。可能有数百个,也可能有几十个。有 1,000 项硬性上限。
- 托管 bean 会在初始化lazyModel 之前尝试获取 20 个项目,因此如果项目少于 20 个,我可以设置正确的数量,但会低于 0.1% 的情况。
【问题讨论】:
-
你应该计算之前的项目,就像一个轻计数查询,如果它是空的,至少只是第一次......
-
@HatemAlimam 这不是数据库查询——在我全部阅读之前,数量真的是未知的——而且获取这些物品的成本相当高,所以重点是只按需加载它们。我根据需求规范用前 20 个项目初始化 managedBean。
-
组件在设计上依赖于计数,最好的办法是在某处捕获该异常......
-
@HatemAlimam 在我的代码返回后由 facesEngine 引发异常,我能想到的唯一方法是设置一个过滤器并在 chain.doFilter 上尝试捕获它()。在应用程序上设置过滤器将超出我正在设计的组件的范围。
-
查看 github 问题。数据表有一个“解决方案”,我认为可以移植到数据滚动器。有关其他解决方法,请参阅 googlecode 中的旧问题列表。搜索“未知数”
标签: jsf-2 primefaces lazy-loading