20

我有一个简单的查询,如下“从用户中选择 *”。我还使用 Pageable 来启用分页。

此查询可能具有基于给定参数是否为空的可选谓词。

例如,如果给出“code”参数且不为空,则查询变为“select * from USERS where code = :code”;

据我所知,我无法使用 @Query 注释来实现这一点。我可以实现自定义存储库并使用 EntityManager 创建动态查询。但是,我不确定如何将“Pageable”与之集成以获取分页结果。

我怎样才能做到这一点?

4

4 回答 4

16

这在 Spring Data 中使用 QueryDSL(作为标准 API 的替代方案)很容易做到。使用以下 QueryDSLPredicateExecutor 方法开箱即用地支持它,如果不应用任何限制,您可以将 null 作为 Predicate 传递:

Page<T> findAll(com.mysema.query.types.Predicate predicate,
                Pageable pageable)

使用 QueryDSL 可能不是您的选择,但是如果您查看以下系列教程,您可能会得到一些想法。

http://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-part-nine-conclusions/

作者在其指南第 9 部分的评论中实际上讨论了您所拥有的场景。

于 2013-10-31T19:22:41.407 回答
4

获取 querydsl 查询的页面结果有点复杂,因为您需要两个查询:一个用于条目总数,另一个用于页面中您需要的条目列表。您可以使用以下超类:

public class QueryDslSupport<E, Q extends EntityPathBase<E>> extends QueryDslRepositorySupport {

  public QueryDslSupport(Class<E> clazz) {
    super(clazz);
  }

  protected Page<E> readPage(JPAQuery query, Q qEntity, Pageable pageable) {
    if (pageable == null) {
      return readPage(query, qEntity, new QPageRequest(0, Integer.MAX_VALUE));
    }
    long total = query.clone(super.getEntityManager()).count(); // need to clone to have a second query, otherwise all items would be in the list
    JPQLQuery pagedQuery = getQuerydsl().applyPagination(pageable, query);
    List<E> content = total > pageable.getOffset() ? pagedQuery.list(qEntity) : Collections.<E> emptyList();
    return new PageImpl<>(content, pageable, total);
  }

}
于 2014-12-13T01:08:42.957 回答
1

例如,您必须使用querydsl和构建您的where依赖非空参数

BooleanBuilder where = new BooleanBuilder();
...
    if(code  != null){
        where.and(YOURENTITY.code.eq(code));
    } 

并在执行查询后

    JPAQuery query = new JPAQuery(entityManager).from(..)               
            .leftJoin( .. )
            ...
            .where(where)

并使用您自己的页面

    MaPage<YOURENTITY> page = new MaPage<YOURENTITY>();
    page.number = pageNumber+1;

    page.content = query.offset(pageNumber*pageSize).limit(pageSize).list(...);

    page.totalResult = query.count();

我这样创建 MyPage

public class MaPage<T> {

    public List<T> content;
    public int number;
    public Long totalResult;
    public Long totalPages;
    ...
}

它可以工作,但是如果在您的查询中您获得了 fetch ,那么您将收到此警告

十一月 2014 年 2 月 21 日上午 6:48:54 org.hibernate.hql.internal.ast.QueryTranslatorImpl 列表
警告:HHH000104:使用集合获取指定的 firstResult/maxResults;在内存中应用!

它会减慢您的请求因此解决方案是获取并定义一个@BatchSize(size=10)并用于Hibernate.initialize(....)获取集合和其他对象类型中的数据。

通过设置 @BatchSize 显示来自相关实体的数据以避免延迟初始化异常

如何使用 Spring Data 和 QueryDSL 执行带有分页的 JPAQuery

于 2014-11-21T06:51:33.573 回答
0

这里的信息已经过时了。让您的存储库实现QueryDslPredicateExecutor并免费提供分页。

于 2017-03-14T15:23:43.643 回答