4

I have this request working good with queryDSL :

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

But what is its equivalent if we use it with spring data jpa

ao_respository.findAll(Predicate arg0, Pageable arg1);

Because i want to return a Page and just with querydsl it doesn't implement Page without spring data jpa.

I try to put my where in Predicate arg0 but i got this exception

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

where lot is declared as QLot lot = QLot.lot;

2
  • I'm also looking for an answer. How about rephrasing your question to something like "How to execute a JPAQuery with pagination using Spring Data and QueryDSL".... I know you have tags, but the title isn't helping for getting answers. Commented Nov 21, 2014 at 1:43
  • I propose a solution but there is a warning at the end Commented Nov 21, 2014 at 6:55

3 Answers 3

7

Returning a 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);

And I created this function to get 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);
}
Sign up to request clarification or add additional context in comments.

1 Comment

fetchCount is deprecated now
5

I created my own Page class and executed the query like this:

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

My Page class:

public class MaPage<T> {

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

It works but I got this warning

nov. 21, 2014 6:48:54 AM org.hibernate.hql.internal.ast.QueryTranslatorImpl list WARN: HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!

3 Comments

When you join fetch a collection property pagination can't be applied on the SQL level.
Yes but there is not a altenative to avoid this warning ? Because i need yo use fetch to display data on my page.
You can avoid this warning if you get rid of left join fetch and use for example batch fetching for the collection members.
1

If you have a working, complex query in querydsl and you want to use springdata pagination, you have to:

  1. make your querydsl/repository method return Page<T>

     Page<YourEntity> yourSelect(Pageable aPageable)
    
  2. use querydsl offset and limit to page your result set

    List<YourEntity>  theResultList = jpaQueryFactory
                    .select(<whatever complext jpaquery you like>)
                    .offset(aPageable.getOffset())
                    .limit(aPageable.getPageSize())
                    .fetch();                                                          
    
  3. provide a LongSuplier counting all available results with respect to your query and use PageableExecutionUtils to return the result as Page

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

1 Comment

it would be nice to have a reference with examples

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.