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(); line and saying 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:
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. Not in this case however, because the class is a Long and it doesn't correspond to an entity class.
Oracle's JAVA EE Tutorial
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With