gpt4 book ai didi

spring - 当 Specification 和 Pageable 一起使用时如何禁用计数?

转载 作者:IT老高 更新时间:2023-10-28 13:59:19 31 4
gpt4 key购买 nike

JpaSpecificationExecutor 附带的方法不足,他们都没有给我我想要的:

Page<T> findAll(Specification<T> spec, Pageable pageable)

List<T> findAll(Specification<T> spec)

List<T> findAll(Specification<T> spec, Sort sort)

第一个方法执行分页查询和计数查询。接下来的 2 根本不执行分页。我需要的是以下之一:

Slice<T> findAll(Specification<T> spec, Pageable pageable)

List<T> findAll(Specification<T> spec, Pageable pageable)

通过不扩展 JpaSpecificationExecutor,我能够执行两个查询,但计数查询也是如此。在我的情况下,必须避免计数查询,因为它非常昂贵。问题是如何?

最佳答案

SimpleJpaRepositoryfindAll(Specification, Pageable)readPage(TypedQuery, Pageable, Specification) 方法。看来 Spring 的实现是在执行 select 查询之前总是执行一个计数查询并检查 startIndex 是否超出范围:

protected Page<T> readPage(TypedQuery<T> query, Pageable pageable, Specification<T> spec) {

query.setFirstResult(pageable.getOffset());
query.setMaxResults(pageable.getPageSize());

Long total = QueryUtils.executeCountQuery(getCountQuery(spec));
List<T> content = total > pageable.getOffset() ? query.getResultList() : Collections.<T> emptyList();

return new PageImpl<T>(content, pageable, total);
}

我不认为这始终是最佳做法。例如,在我的用例中,我们很乐意预先执行一次计数查询,而不是在后续调用中执行,因为我们知道新数据的出现频率不足以保证计数更新,而且计数查询的执行成本非常高。

如果 Spring Data 可以提供一个标志或替代方法来禁用条件查询的计数,那就太好了,类似于 simple find queries .

同时,这是我的变通解决方案:

创建一个继承 SimpleJpaRepository 的内部类。覆盖 readPage 以禁用计数查询。创建一个DAO,使用@Repository 对其进行注释并实例化这个内部类以传递正确的EntityManager。最后,在“无计数”条件搜索适用的地方注入(inject)此 DAO:

@Repository
public class CriteriaNoCountDao {

@PersistenceContext
protected EntityManager em;

public <T, ID extends Serializable> Page<T> findAll(Specification<T> spec, Pageable pageable, Class<T> clazz){
SimpleJpaNoCountRepository<T, ID> noCountDao = new SimpleJpaNoCountRepository<T, ID>(clazz, em);
return noCountDao.findAll(spec, pageable);
}

/**
* Custom repository type that disable count query.
*/
public static class SimpleJpaNoCountRepository<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> {

public SimpleJpaNoCountRepository(Class<T> domainClass, EntityManager em) {
super(domainClass, em);
}

/**
* Override {@link SimpleJpaRepository#readPage(TypedQuery, Pageable, Specification)}
*/
protected Page<T> readPage(TypedQuery<T> query, Pageable pageable, Specification<T> spec) {
query.setFirstResult(pageable.getOffset());
query.setMaxResults(pageable.getPageSize());

List<T> content = query.getResultList();

return new PageImpl<T>(content, pageable, content.size());
}
}
}

关于spring - 当 Specification 和 Pageable 一起使用时如何禁用计数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26738199/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com