我正在使用来自Primefaces的Datatable延迟加载。过滤值时,返回记录的大小小于我用于寻呼机的绝对计数。所以数据表中有空页。但我也无法使用从查询中获取的记录大小的大小,因为查询可能只返回一个子集。
实施例: 数据库中有30条记录,数据表中的页面大小为10,所以有3页,每个延迟加载请求我返回10条记录。
当我输入过滤器时,只剩下20条记录。由于绝对计数,寻呼机仍然显示3页。但是当我将记录数改为我返回的10条记录时,没有第二页。那么如何才能获得所有过滤记录的数量?有自己的查询吗?
答案 0 :(得分:1)
非常多,是您自己的查询:
关于您的问题的一些讨论: Total row count for pagination using JPA Criteria API
答案 1 :(得分:1)
我使用以下策略。
首先,我创建了一个通用数据模型。这个数据模型取决于我设计我的实体(JPA),我的过滤器类和我的可分页服务的方式。请注意,我使用pojo来传输搜索条件,您需要进行一些小的更改才能使用地图过滤器参数。
以下是生成的数据模型:
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortMeta;
import org.primefaces.model.SortOrder;
public class GenericDataModel<ENTITY extends AbstractEntity, FILTER extends AbstractFilter, SERVICE extends Paginable<ENTITY, FILTER>>
extends LazyDataModel<ENTITY> {
private FILTER filter;
private SERVICE service;
private boolean started;
//use this constructor if you want to show some result on page load
public GenericDataModel(FILTER filter, SERVICE service) {
this(filter, service, true);
}
public GenericDataModel(FILTER filter, SERVICE service, boolean autoStart) {
this.filter = filter;
this.service = service;
started = autoStart;
count();
}
@Override
public List<ENTITY> load(int first, int pageSize,
List<SortMeta> multiSortMeta, Map<String, String> filters) {
if (!started) {
return new ArrayList<ENTITY>();
}
if (getRowCount() <= 0) {
count();
}
//deal with sorting here. I do that by inserting them into the filter.
return service.find(filter);
}
@Override
public List<ENTITY> load(int first, int pageSize, String sortField,
SortOrder sortOrder, Map<String, String> filters) {
if (!started) {
return new ArrayList<ENTITY>();
}
if (getRowCount() <= 0) {
count();
}
//deal with sorting here. I do that by inserting them into the filter.
return service.find(filter);
}
public void count() {
if (!started) {
setRowCount(0);
return;
}
Long rowCount = service.count(filter);
setRowCount(rowCount == null ? 0 : rowCount.intValue());
}
public void start() {
started = true;
}
}
以下是我在托管bean上使用它的方法:
@Inject
private ProfessorService professorService;
private ProfessorFilter professorFilter;
private GenericDataModel<Professor, ProfessorFilter, ProfessorService> dataModel;
@PostConstruct
public String setup() {
professorFilter = new ProfessorFilter();
dataModel = new GenericDataModel(professorFilter, professorService, false);
return null;
}
//action for the search button on the view
public void search() {
dataModel.start();
dataModel.count();
}
paginableService.count 方法使用select count(*)
方法生成的查询所使用的相同join和where子句执行paginableService.find(filter)
。
对于真正庞大的数据,您可能会发现这个额外的查询可能会浪费时间和资源,但请记住,只有当您的搜索条件发生变化时才会执行此额外查询。