使用延迟加载和记录计数筛选数据的最佳做法



我正在使用来自Primefaces的Datatable,延迟加载。筛选值时,返回的记录的大小小于我用于寻呼机的绝对计数。因此,数据表中存在空白页。但我也不能使用从查询中获得的记录大小的大小,因为查询可能只返回一个子集。

例:数据库中有 30 条记录,数据表中的页面大小为 10,所以有 3 页,每个延迟加载请求我返回 10 条记录。

当我输入过滤器时,只剩下 20 条记录。由于绝对计数,寻呼机仍显示 3 页。但是,当我将记录计数更改为返回的 10 条记录时,没有第二页。那么如何获取所有筛选记录的计数呢?有自己的查询?

我使用以下策略。

首先,我创建了一个通用数据模型。此数据模型取决于我设计实体 (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 方法使用与paginableService.find(filter)方法的结果查询相同的连接和 where 子句执行select count(*)

对于非常大的数据,您可能会发现这种额外的查询可能会浪费时间和资源,但请记住,只有在搜索条件更改时,才会完成此额外查询。

几乎是的,使用您自己的查询:

关于您的问题的一些讨论:使用 JPA 条件 API 进行分页的总行数

最新更新