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

时间:2015-06-16 12:18:41

标签: spring spring-data spring-data-jpa querydsl

我尝试创建一个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?所述,我尝试使用&#34;技巧&#34;使用&#34; findAllBy&#34;。

命名方法

但是当我调用它时,我得到了这个异常(它试图将参数作为&#34;查询的参数&#34;):

java.util.NoSuchElementException
    at java.util.ArrayList$Itr.next(ArrayList.java:834)
    at java.util.Collections$UnmodifiableCollection$1.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$1.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)

当我删除Predicate时,不会发生此异常,例如:

List<Entity> findAllBy(Pageable pageable);

问题是:

如何使用Pageable创建QueryDSL存储库而不发出计数查询?进行额外查询以获取最后一页之后的下一页更为便宜,而不是为每个页面请求发出额外的计数查询。

1 个答案:

答案 0 :(得分:2)

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

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

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