使用Spring Data和QueryDSL执行JPA查询并进行分页的方法

4

我使用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);

因为我想返回一个页面,只有使用querydsl时,没有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;


我也在寻找答案。你可以尝试重新表达你的问题,比如说“如何使用Spring Data和QueryDSL执行带分页的JPA查询”……虽然你已经加了标签,但标题并没有很好地帮助你得到答案。 - pakman
我更新了标题 ;) - Hayi
我提出了一个解决方案,但是最后有一个警告。 - Hayi
3个回答

7

返回一个页面

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);
}

fetchCount现在已经被弃用。 - undefined

5
我创建了自己的页面类,并像这样执行查询:
    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;
    ...
}

这段代码可以正常运行,但是会出现以下警告:

2014年11月21日上午6:48:54
org.hibernate.hql.internal.ast.QueryTranslatorImpl list WARN:
HHH000104:在集合提取中指定了firstResult/maxResults;正在内存中应用!


3
当您使用 fetch 加入一个集合属性时,无法在 SQL 层面上应用分页。 - Timo Westkämper
是的,但是有没有避免这个警告的替代方案?因为我需要使用fetch在页面上显示数据。 - Hayi
2
如果你摆脱左连接获取并且使用例如批量获取集合成员,你就可以避免这个警告。 - Timo Westkämper

1

如果您在querydsl中有一个工作的复杂查询,并且想要使用springdata分页,您需要执行以下操作:

使您的 QueryDSL/Repository 方法返回 `Page`:
``` Page yourSelect(Pageable aPageable) ```
使用 QueryDSL 的 `offset` 和 `limit` 对结果集进行分页:
``` List theResultList = jpaQueryFactory .select() .offset(aPageable.getOffset()) .limit(aPageable.getPageSize()) .fetch(); ```
提供一个 `LongSupplier` 来计算关于您的查询的所有可用结果,并使用 `PageableExecutionUtils` 以 `Page` 的形式返回结果:
``` final long theCount = jpaQueryFactory .selectFrom() .fetchCount();
return PageableExecutionUtils.getPage(theResultList, aPageable, () -> theCount); ```

带有示例的参考资料会很好。 - Marcello DeSales

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接