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

时间:2014-07-22 06:52:04

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

我的此请求适用于queryDSL

 Iterable<AO> query_result = new JPAQuery(entityManager).from(ao)
            .leftJoin( ao.lots , lot )
            .leftJoin( ao.acs , ac )
              .where(where).distinct()
                .list(ao);

但是如果我们将它与spring data jpa

一起使用,它的等价物是什么
ao_respository.findAll(Predicate arg0, Pageable arg1);

因为我想要返回Page而只是querydsl,所以在没有Page的情况下,它不会实现spring data jpa

我尝试将where放入Predicate arg0,但我得到了这个例外

Undeclared path 'lot '. Add this path as a source to the query to be able to reference it

其中lot被声明为QLot lot = QLot.lot;

3 个答案:

答案 0 :(得分:3)

我创建了自己的Page类并执行了这样的查询:

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




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

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

    page.totalResult = query.count();

我的网页课程:

public class MaPage<T> {

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

它有效,但我收到了这个警告

  

十一月21,2014 6:48:54 AM   org.hibernate.hql.internal.ast.QueryTranslatorImpl list WARN:   HHH000104:使用collection fetch指定的firstResult / maxResults;   在记忆中应用!

答案 1 :(得分:1)

返回Page

JPAQuery query = 
    ...
    .orderBy(getOrderSpecifiers(pageable, MyEntity.class))
    .limit(pageable.getPageSize())
    .offset(pageable.getOffset());

long total = query.fetchCount();
List<MyEntity> content = query.fetch();
return new PageImpl<>(content, pageable, total);

我创建了此函数以获取OrderSpecifier

private OrderSpecifier[] getOrderSpecifiers(@NotNull Pageable pageable, @NotNull Class klass) {

    // orderVariable must match the variable of FROM
    String className = klass.getSimpleName();
    final String orderVariable = String.valueOf(Character.toLowerCase(className.charAt(0))).concat(className.substring(1));

    return pageable.getSort().stream()
            .map(order -> new OrderSpecifier(
                    Order.valueOf(order.getDirection().toString()),
                    new PathBuilder(klass, orderVariable).get(order.getProperty()))
            )
            .toArray(OrderSpecifier[]::new);
}

答案 2 :(得分:0)

如果您在 querydsl 中有一个有效的、复杂的查询,并且您想使用 springdata 分页,则必须:

  1. 使您的 querydsl/repository 方法返回 Page<T>

     Page<YourEntity> yourSelect(Pageable aPageable)
    
  2. 使用 querydsl offsetlimit 对结果集进行分页

    List<YourEntity>  theResultList = jpaQueryFactory
                    .select(<whatever complext jpaquery you like>)
                    .offset(aPageable.getOffset())
                    .limit(aPageable.getPageSize())
                    .fetch();                                                          
    
  3. 提供一个 LongSuplier 计算与您的查询相关的所有可用结果,并使用 PageableExecutionUtils 将结果返回为 Page

    final long theCount = jpaQueryFactory
          .selectFrom(<your select to count all results>)
          .fetchCount();
    
    return PageableExecutionUtils.getPage(theResultList, aPageable, () -> theCount);