在结果列表很大的情况下,Java端 计数 和子 列表 操作对于内存使用可能是危险的,因此在性能方面也很危险。
相反,我通常采用以下方法: 使用2个查询
,一个用于计数过滤后的resultSet(我让db进行计数),另一个用于检索分页的resultSet(我让db提取子列表)。即使对于包含数百万行的表,我也从未经历过明显的延迟。
遵循有关排序和过滤的具体示例。所有代码都使用JPA标准(没有Hibernate或Spring自定义功能)。
CriteriaQuery在这种情况下,特别指出了这种方法。
MyBean类
@ManagedBean@ViewScopedpublic 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类
@Statelesspublic 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(); }}


