0

I'm trying to create a spring data repository with a method to list a page of entities and a QueryDSL predicate using this:

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

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

}

As mentioned here Way to disable count query from PageRequest for getting total pages?, I'm tryng to use the "trick" naming the method with "findAllBy".

But when I invoke it, I'm getting this exception (it is trying to use the parameters as "parameters of the query"):

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)

This exception doesn't occurs when I remove the Predicate, example:

List<Entity> findAllBy(Pageable pageable);

The question is:

How can I create a QueryDSL Repository with Pageable without emit the count query? Is more inexpensive to do an extra query to get the next page after the last page instead of emit an extra count query to each page request.

Community
  • 1
  • 1
Beto Neto
  • 3,962
  • 7
  • 47
  • 81
  • Why do you want this? – M. Deinum Jun 16 '15 at 13:33
  • @M.Deinum : Performance of course! Is more inexpensive to do an extra query to get the next page after the last page instead of emit an extra count query to each page request. – Beto Neto Jun 16 '15 at 13:38
  • A count query shouldn't take that long with a decent database. But I guess that trick won't work in this case as it will only work with the plain repositories not with an executor. You would have to implement a custom method for this to work. – M. Deinum Jun 16 '15 at 13:42
  • @M.Deinum This isn't a issue about "decent database", this is about a complex filter that, for example, perform a full-scan on the table twice totally unnecessary only for counting. But, how can I create a custom method to do this in a generic repository ? – Beto Neto Jun 16 '15 at 13:48
  • 1
    That is explained in [the reference guide](http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-implementations). – M. Deinum Jun 16 '15 at 13:49
  • @M.Deinum I solved with the reference guide, thanks a lot! Can you provide your comment as a Answer? – Beto Neto Jun 16 '15 at 14:40

1 Answers1

3

This is basically invalid usage of the query derivation mechanism. Executing Predicate instances and query methods are a distinct mechanisms that cannot be intermingled. You basically declare a query method that doesn't take any parameters (does not have any criterias) bit then takes a Predicate that

Unfortunately the methods declared in repository base interfaces and QueryDslPredicateExecutor can only be redeclared to return more concrete types (e.g. overriding findAll() to return List<T> instead of Iterable<T> as the implementation actually returns a type implementing that more concrete type).

I suggest to create a custom implementation as described here.

Oliver Drotbohm
  • 80,157
  • 18
  • 225
  • 211