【问题标题】:How to use Criteria And pagination如何使用标准和分页
【发布时间】:2018-09-10 15:03:39
【问题描述】:

大家好,我正在尝试将条件与分页一起使用,但我的代码不起作用,这里是:

public Page<Person> getAuthorizationsTest() {

    PageRequest pageRequest = new PageRequest(1, 5);

    CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
    CriteriaQuery<Person> queryBase = criteriaBuilder.createQuery(Person.class);
    Root<Person> root = queryBase.from(Person.class);
    List<Predicate> queryConditions = new ArrayList<>();

    Predicate predicate = criteriaBuilder.like(root.get("name"), "%[myValue]%");
    queryConditions.add(predicate);

    queryBase.where(queryConditions.toArray(new Predicate[]{}));

    TypedQuery<Person> query = em.createQuery(queryBase);

    List<Person> list = query.getResultList();

    Page<Person> authorizations = new PageImpl<Person>(list, pageRequest, list.size());

    return authorizations;
}

一切看起来都很好,但是当我执行它时,我会收到一个包含所有结果的列表页面,而不仅仅是我的 pageRequest 中指定的结果

我做错了什么?

【问题讨论】:

    标签: java spring-boot pagination criteria


    【解决方案1】:

    谓词数组和 where 子句看起来定义正确。在这些行中:

    谓词谓词 = criteriaBuilder.like(root.get("name"), "%[myValue]%"); queryConditions.add(predicate);

    queryBase.where(queryConditions.toArray(new Predicate[]{}));
    
    TypedQuery<Person> query = em.createQuery(queryBase);
    

    只是一个提醒。也许你需要criteriaBuilder.equal 而不是criteriaBuilder.like。如果你确定你做了什么,你可以省略这个提醒。

    您需要更改以下几行:

    query.setFirstResult(Math.toIntExact(pageRequest.getOffset()));
    query.setMaxResults(pageRequest.getPageSize());
    
    return new PageImpl<Person>(query.getResultList(), pageRequest, getTotalCount(criteriaBuilder, queryConditions));
    

    然后为了保持一致性,添加getTotalCount方法。

    private Long getTotalCount(CriteriaBuilder criteriaBuilder, Predicate[] predicateArray) {
            CriteriaQuery<Long> criteriaQuery = criteriaBuilder.createQuery(Long.class);
            Root<T> root = criteriaQuery.from(entityType);
    
            criteriaQuery.select(criteriaBuilder.count(root));
            criteriaQuery.where(predicateArray);
    
            return entityManager.createQuery(criteriaQuery).getSingleResult();
        }
    

    【讨论】:

    • 嗨@gokhanbirincii 我使用了你的解决方案,现在我在setFirstResultsetMaxResults 上遇到了这个错误,这是错误:java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended 这可能是什么?我使用 Oracle 10g 只是为了让你知道
    • 您确定 pageRequest.getOffset() 和 pageRequest.getPageSize() 不是 Nullempty。你能发送整个错误日志吗?
    • 嗨,它只有在我删除 query.setMaxResults(pageRequest.getPageSize()); 时才有效,否则它会给我错误 Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended... 尝试将我的 .properties 更改为 hibernate.dialect = org.hibernate.dialect.Oracle10gDialect 但也没有用,有什么想法吗?
    【解决方案2】:

    您没有使用分页请求:

    列表列表 = query.getResultList();

    这个查询会一直查询所有的结果,效率很低。

    相反,您应该使用 Spring 方式,即您应该使用扩展 PagingAndSortingRepository 的存储库接口(例如 JpaRepository 接口)。

    然后只需使用一种方法对结果进行分页,例如 documentation 中所述的 findAll :

    PagingAndSortingRepository<User, Long> repository = // … get access to a bean
    Page<User> users = repository.findAll(new PageRequest(1, 20));
    

    【讨论】:

    • 嘿 Laurent B 感谢您的帮助,我展示了我的代码的简化版本,实际上它有多种过滤器可能会使用也可能不会使用,因此将我的代码重新定义为“Spring Way”在这种情况下不是一个选项
    • 好吧,然后按照 gokhanbirincii 的回答中所述使用 setFirstResult 和 setMaxResults
    • 专问如何使用Criteria。
    猜你喜欢
    • 1970-01-01
    • 2011-09-15
    • 2015-12-18
    • 1970-01-01
    • 2014-08-16
    • 1970-01-01
    • 2012-10-16
    • 1970-01-01
    • 2016-04-06
    相关资源
    最近更新 更多