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

如何使用延迟加载和分页查询Primeface dataTable的数据

方梓
2023-03-14

在我的JSF的数据中,我已经实现了延迟加载,当我分页通过记录时,执行下一组记录需要大约4到5秒钟的时间,实际上执行结果应该不到一秒钟。

这种情况发生在我实现它的方式上,我不知道如何解决这个问题。

扩展LazyDataModel的DataModel类

@Override
public List<Request> load(int startingAt, int maxPerPage, String sortField,
                          SortOrder sortOrder, Map<String, String> filters)
{
    requestList = requestService.getRequest(startingAt, maxPerPage,
                                            sortField, sortOrder, filters);
    this.setRowCount(requestList.size());
    if (requestList.size() > maxPerPage)
    {
        System.out.println("executing");
        return requestList.subList(startingAt, startingAt + maxPerPage);
    }
    else
    {
        System.out.println("executing else ");
        return requestList;
    }

    return requestList;
}

在道课上

@Override
public List<Request> getRequest(int startingAt, int maxPerPage,
                                String sortField, SortOrder sortOrder, Map<String, String> filters)
{
    Criteria criteria = sessionFactory.getCurrentSession().createCriteria(
                            Request.class);
    criteria.addOrder(Order.desc("requestNo"));
    for (Map.Entry<String, String> entry : filters.entrySet())
    {
        if (entry.getValue() != null)
        {
            criteria.add(Restrictions.ilike("requestNo",
                                            "%" + entry.getValue() + "%"));
        }
    }
    //criteria.setMaxResults(maxPerPage);
    //criteria.setFirstResult(startingAt);
    return criteria.list();
}

有人能解释一下是什么原因导致了这些记录分页的延迟吗?

如果我删除以下内容

if (requestList.size() > maxPerPage)
{
    System.out.println("executing");
    return requestList.subList(startingAt, startingAt + maxPerPage);
}
else
{
    System.out.println("executing else ");
    return requestList;
}

并执行,然后它是完全执行没有延迟,然而问题是this.setRowCount(请求ist.size ());总是5,这是我的每页默认记录数。

更新2

@Override
    public List<Request> load(int startingAt, int maxPerPage, String sortField,
            SortOrder sortOrder, Map<String, String> filters) {
        requestList = requestService.getRequest(startingAt, maxPerPage,
                sortField, sortOrder, filters);
        this.setRowCount(requestService.getRequestCount());
        if (requestService.getRequestCount() > maxPerPage) {
            try {

                return requestList.subList(startingAt, startingAt + maxPerPage);
            } catch (IndexOutOfBoundsException e) {
                //e.printStackTrace();
                return requestList.subList(startingAt, startingAt
                        + (requestService.getRequestCount() % maxPerPage));
            }
        } else {
            return requestList;
        }       
    }

使用不同的查询获取resultset的计数,方法如下

@Override
    public int count() {
        int count = ((Long) sessionFactory.getCurrentSession()
                .createQuery("select count(*) from Request").uniqueResult())
                .intValue();
        System.out.println(" count size " + count);
        return count;
    }

还有我的刀

@Override
        public List<Request> getRequest(int startingAt, int maxPerPage,
                String sortField, SortOrder sortOrder, Map<String, String> filters) {
            Criteria criteria = sessionFactory.getCurrentSession().createCriteria(
                    Request.class);
            criteria.addOrder(Order.desc("requestNo"));
            for (Map.Entry<String, String> entry : filters.entrySet()) {
                if (entry.getValue() != null) {
                    criteria.add(Restrictions.ilike("requestNo",
                            "%" + entry.getValue() + "%"));         }
            }
             criteria.setMaxResults(maxPerPage);
             criteria.setFirstResult(startingAt);       
                return criteria.list(); 

        }

共有2个答案

马新觉
2023-03-14

我不确定这是否与本例相关,但除了@perissf的观察之外,我还担心以下几点:

if (entry.getValue() != null)
{
    criteria.add(Restrictions.ilike("requestNo",
                                    "%" + entry.getValue() + "%"));
}

因为这将解析成类似于

WHERE UPPER(request_no) LIKE '%VALUE%'

这将是全表扫描,因为在本例中无法使用请求上的索引。\u no,这对于具有大量行的表来说非常慢,原因有二:

  • UPPER(请求编号)需要功能索引
  • 像“%anything”一样,无论函数索引是否存在,都必须检查请求\u no的每个值
公冶嘉
2023-03-14

在结果列表非常大的情况下,Java端计数和子列表操作可能会对内存使用造成危险,从而也会影响性能。

相反,我通常使用以下方法:使用两个查询,一个用于计算过滤后的结果集(我让db进行计数),另一个用于检索分页后的结果集(我让db提取子列表)。我从未经历过明显的延迟,即使是包含数百万行的表。

下面是一个具体的排序和过滤示例。所有的代码都使用JPA标准(没有Hibernate或Spring自定义功能)在这种情况下,CriteriaQuery方法会被特别指出。

MyBean类

@ManagedBean
@ViewScoped
public class MyBean {
    @EJB
    private MyObjFacade myObjFacade;
    private LazyDataModel<MyObjType> model;        // getter and setter

    @PostConstruct
    public void init() {
        model = new LazyDataModel<MyObjType> () {

            @Override
            public List<MyObjType> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters) {
                model.setRowCount(myObjFacade.count(filters));
                return myObjFacade.getResultList(first, pageSize, sortField, sortOrder, filters);
            }
        };
        model.setRowCount(myObjFacade.count(new HashMap<String, String> ()));
    }
}

MyObjFacade类

@Stateless
public class MyObjFacade {
    @PersistenceContext
    private EntityManager em;
    @EJB
    private MyObjFacade myObjFacade;

    private Predicate getFilterCondition(CriteriaBuilder cb, Root<MyObjType> myObj, Map<String, String> filters) {
        Predicate filterCondition = cb.conjunction();
        String wildCard = "%";
        for (Map.Entry<String, String> filter : filters.entrySet()) {
            String value = wildCard + filter.getValue() + wildCard;
            if (!filter.getValue().equals("")) {
                javax.persistence.criteria.Path<String> path = myObj.get(filter.getKey());
                filterCondition = cb.and(filterCondition, cb.like(path, value));
            }
        }
        return filterCondition;
    }

    public int count(Map<String, String> filters) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<Long> cq = cb.createQuery(Long.class);
        Root<MyObjType> myObj = cq.from(MyObjType.class);
        cq.where(myObjFacade.getFilterCondition(cb, myObj, filters));
        cq.select(cb.count(myObj));
        return em.createQuery(cq).getSingleResult().intValue();
    }

    public List<MyObjType> getResultList(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<MyObjType> cq = cb.createQuery(MyObjType.class);
        Root<MyObjType> myObj = cq.from(MyObjType.class);
        cq.where(myObjFacade.getFilterCondition(cb, myObj, filters));
        if (sortField != null) {
            if (sortOrder == SortOrder.ASCENDING) {
                cq.orderBy(cb.asc(myObj.get(sortField)));
            } else if (sortOrder == SortOrder.DESCENDING) {
                cq.orderBy(cb.desc(myObj.get(sortField)));
            }
        }
        return em.createQuery(cq).setFirstResult(first).setMaxResults(pageSize).getResultList();
    }
}
 类似资料:
  • 问题内容: 在我的JSF数据表中,我实现了延迟加载,当我对记录进行分页时,执行下一组记录大约需要4到5秒的时间,实际上执行结果应该少于一秒钟。 这是我实现它的方式所发生的,不确定我该如何解决。 扩展LazyDataModel的DataModel类 和道课 有人可以解释是什么原因导致了记录分页时出现延迟吗? 如果我删除以下内容 并执行,那么它可以完美执行而没有延迟,但是问题始终是5,这是我每页的默认

  • 我正在使用slick.js构建一个旋转木马。但是,即使我将属性从更改为,在我滚动到该图像之前,图像仍然会被加载。我怀疑这是因为我的图像中有标记。我的问题是如何防止浏览器加载响应图像,或者如何正确地延迟加载响应图像。 这是我的img标签的样本

  • 描述 (Description) 延迟加载可应用于图像,背景图像和淡入效果,如下所述 - 对于图像 要在图像上使用延迟加载,请按照给定的步骤进行操作 - 使用data-src属性而不是src属性来指定图像源。 将类lazy添加到图像。 <div class = "page-content"> ... <img data-src = "image_path.jpg" class = "l

  • 我正在使用Mika Tuupola的jQuery延迟加载。 是否可以在每次延迟加载图像后调用函数。 我打算做的是跟踪图像的浏览次数。因此,如果图像是延迟加载的,这意味着用户已经看到了图像,我将通过在后台执行HTTP GET,将数据库中的计数器增加1。

  • 这是我在Stack Overflow上的第一篇文章。在发布之前,我研究了很多。在我使用Java Primefaces的系统中,我使用普通的SQL。我在第三个企业项目中,我更喜欢这种方式。 我找不到任何使用普通SQL的例子,只有使用框架(JPA等) 我知道在数组列表中我会手动传递限制。选择... from... ORDER BY... LIMIT 但是我需要一个完整的例子,使用数据库(不是内存中的静

  • 我正在尝试在我正在构建的天气应用程序中实现SwipeToRe新鲜布局。当用户滑动刷新时,ViewModel中的数据应该更新,然后视图应该相应地更新。 这是我的货币天气片段的片段: 我的视图模型: 我的lazyDeferred实现: 目前,通过此设置,forecastRepository。当在应用程序启动或切换到该片段时加载该片段时,会调用ViewModel中的getWeather()函数,但在滑动