【问题标题】:Spring data repository QueryDslPredicateExecutor without pageable count没有可分页计数的 Spring 数据存储库 QueryDslPredicateExecutor
【发布时间】:2015-09-01 06:14:36
【问题描述】:

我正在尝试使用以下方法创建一个 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?,我正在尝试使用“技巧”来命名带有“findAllBy”的方法。

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

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)

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

List<Entity> findAllBy(Pageable pageable);

问题是:

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

【问题讨论】:

  • 你为什么要这个?
  • @M.Deinum :当然是性能!在最后一页之后执行额外查询以获取下一页而不是向每个页面请求发出额外的计数查询更便宜。
  • 一个体面的数据库不应该花费那么长时间的计数查询。但我想这个技巧在这种情况下不起作用,因为它只适用于普通存储库而不适用于执行程序。您必须实现一个自定义方法才能使其工作。
  • @M.Deinum 这不是关于“体面数据库”的问题,而是关于一个复杂的过滤器,例如,对表执行两次完全扫描,仅用于计数。但是,如何在通用存储库中创建自定义方法来执行此操作?
  • 这在the reference guide中有解释。

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


【解决方案1】:

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

不幸的是,在存储库基接口和QueryDslPredicateExecutor 中声明的方法只能重新声明以返回更具体的类型(例如,覆盖findAll() 以返回List&lt;T&gt; 而不是Iterable&lt;T&gt;,因为实现实际上返回了一个实现更多的类型具体类型)。

我建议按照here 的描述创建一个自定义实现。

【讨论】:

    猜你喜欢
    • 2020-01-07
    • 1970-01-01
    • 2017-12-20
    • 1970-01-01
    • 2021-09-10
    • 2016-07-17
    • 2018-07-19
    • 2019-05-10
    • 1970-01-01
    相关资源
    最近更新 更多