简体   繁体   English

Jpa Criteria API计数

[英]Jpa Criteria API count

I've been trying to get total rows count and to do so, I've used JPA Criteria API but it throws an error at Long count = em.createQuery(sc).getSingleResult(); 我一直试图获得总行数并且这样做,我已经使用了JPA Criteria API,但它在Long count = em.createQuery(sc).getSingleResult();时抛出错误Long count = em.createQuery(sc).getSingleResult(); line and saying java.lang.IllegalStateException: No criteria query roots were specified . line并说java.lang.IllegalStateException: No criteria query roots were specified I've done some research but couldn't narrow the problem. 我做了一些研究,但无法缩小问题范围。

Here's my code snippet; 这是我的代码片段;

@PersistenceContext
    public EntityManager em;

......

public Page<UserDTO> findByCriteria(String filters, Pageable pageable) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<UserDTO> cq = cb.createQuery(UserDTO.class);
        Root<UserDTO> iRoot = cq.from(UserDTO.class);
        List<Predicate> predicates = new ArrayList<Predicate>();

        if (StringUtils.isNotEmpty(filters)) {
            predicates.add(cb.like(cb.lower(iRoot.<String>get("login")), "%" + filters.toLowerCase() + "%"));
        }

        Predicate[] predArray = new Predicate[predicates.size()];
        predicates.toArray(predArray);

        CriteriaQuery<Long> sc = cb.createQuery(Long.class);
        sc.select(cb.count(iRoot));

        sc.where(predArray);
        Long count = em.createQuery(sc).getSingleResult();

        cq.where(predArray);

        List<Order> orders = new ArrayList<Order>(2);
        orders.add(cb.asc(iRoot.get("name")));
        orders.add(cb.asc(iRoot.get("desc")));

        cq.orderBy(orders);
        TypedQuery<UserDTO> query = em.createQuery(cq);

        Page<UserDTO> result = new PageImpl<UserDTO>(query.getResultList(), pageable, count);


        return result;
    }

EDITED AND WORKING CODE; 编辑和工作代码;

public Page<UserDTO> findByCriteria(String columnName, String filters, Pageable pageable) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<UserDTO> cq = cb.createQuery(UserDTO.class);
        Root<UserDTO> iRoot = cq.from(UserDTO.class);
        List<Predicate> predicates = new ArrayList<Predicate>();

        if (StringUtils.isNotEmpty(filters)) {
            predicates.add(cb.like(cb.lower(iRoot.<String>get(columnName)), "%" + filters.toLowerCase() + "%"));
        }

        Predicate[] predArray = new Predicate[predicates.size()];
        predicates.toArray(predArray);

        Long count = calculateCount(filters);

        cq.where(predArray);

        List<Order> orders = new ArrayList<Order>(2);
        orders.add(cb.asc(iRoot.get("firstName")));
        orders.add(cb.asc(iRoot.get("lastName")));

        cq.orderBy(orders);
        TypedQuery<UserDTO> query = em.createQuery(cq);

        Page<UserDTO> result = new PageImpl<UserDTO>(query.getResultList(), pageable, count);


        return result;
    }

    public Long calculateCount(String filters) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Long> sc = cb.createQuery(Long.class);
        Root<UserDTO> iRoot = sc.from(UserDTO.class);
        List<Predicate> predicates = new ArrayList<Predicate>();

        if (StringUtils.isNotEmpty(filters)) {
            predicates.add(cb.like(cb.lower(iRoot.<String>get("login")), "%" + filters.toLowerCase() + "%"));
        }

        Predicate[] predArray = new Predicate[predicates.size()];
        predicates.toArray(predArray);

        sc.select(cb.count(iRoot));

        sc.where(predArray);
        Long count = em.createQuery(sc).getSingleResult();

        return count;

    }

As anticipated in the comment, you need to explicitly add CriteriaQuery#from() method: 正如评论中所预期的那样,您需要从()方法中明确添加CriteriaQuery#

sc.from(UserDTO.class);

The from method is often not used because the API provider defaults to the entity class specified in the CriteriaQuery constructor. 通常不使用from方法,因为API提供程序默认使用CriteriaQuery构造函数中指定的实体类。 Not in this case however, because the class is a Long and it doesn't correspond to an entity class. 但是不是在这种情况下,因为类是Long并且它不对应于实体类。

See also: 也可以看看:

Oracle's JAVA EE Tutorial Oracle的JAVA EE教程

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM