Spring 没有可分页计数的数据存储库 QueryDslPredicateExecutor

Spring data repository QueryDslPredicateExecutor without pageable count

我正在尝试创建一个 spring 数据存储库,其中包含列出实体页面的方法和使用此方法的 QueryDSL 谓词:

public interface EntityRespository extends JpaRepository<Entity, Integer>, QueryDslPredicateExecutor<Entity> {

    List<Entity> findAllBy(Predicate predicate, Pageable pageable);

}

如此处所述Way to disable count query from PageRequest for getting total pages?,我正在尝试使用 "trick" 将方法命名为 "findAllBy"。

但是当我调用它时,我得到了这个异常(它试图将参数用作 "parameters of the query"):

java.util.NoSuchElementException
    at java.util.ArrayList$Itr.next(ArrayList.java:834)
    at java.util.Collections$UnmodifiableCollection.next(Collections.java:1067)
    at org.springframework.data.jpa.repository.query.CriteriaQueryParameterBinder.bind(CriteriaQueryParameterBinder.java:63)
    at org.springframework.data.jpa.repository.query.ParameterBinder.bind(ParameterBinder.java:111)
    at org.springframework.data.jpa.repository.query.ParameterBinder.bindAndPrepare(ParameterBinder.java:172)
    at org.springframework.data.jpa.repository.query.ParameterBinder.bindAndPrepare(ParameterBinder.java:163)
    at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.invokeBinding(PartTreeJpaQuery.java:207)
    at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.createQuery(PartTreeJpaQuery.java:134)
    at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.doCreateQuery(PartTreeJpaQuery.java:74)
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.createQuery(AbstractJpaQuery.java:169)
    at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:113)
    at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:77)
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:100)
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:91)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:393)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:371)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.transaction.interceptor.TransactionInterceptor.proceedWithInvocation(TransactionInterceptor.java:99)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:122)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy86.findAllBy(Unknown Source)

当我删除谓词时不会发生此异常,示例:

List<Entity> findAllBy(Pageable pageable);

问题是:

如何在不发出计数查询的情况下使用 Pageable 创建 QueryDSL 存储库?做一个额外的查询来获取最后一页之后的下一页而不是对每个页面请求发出一个额外的计数查询更便宜。

这基本上是查询派生机制的无效使用。执行 Predicate 个实例和查询方法是一种不同的机制,不能混合使用。您基本上声明了一个不带任何参数(没有任何标准)位的查询方法,然后带一个 Predicate

不幸的是,在存储库基接口和 QueryDslPredicateExecutor 中声明的方法只能重新声明为 return 更具体的类型(例如,将 findAll() 覆盖为 return List<T> 而不是 Iterable<T> 作为实现实际上 return 是一种实现更具体类型的类型)。

我建议按照 here 所述创建自定义实现。