How can I convert a spring data Sort to a querydsl OrderSpecifier?

23,942

Solution 1

You can do somethings like this: But make sure to trim the o.getProperty() so you only pass the property and not "alias."+property

if (pageable != null) {
    query.offset(pageable.getOffset());
    query.limit(pageable.getPageSize());
    for (Sort.Order o : pageable.getSort()) {
        PathBuilder<Object> orderByExpression = new PathBuilder<Object>(Object.class, "object");

        query.orderBy(new OrderSpecifier(o.isAscending() ? com.mysema.query.types.Order.ASC
                : com.mysema.query.types.Order.DESC, orderByExpression.get(o.getProperty())));
    }
}

Solution 2

I don't know if it is still relevant but there is an implementation in the spring data jpa for doing the conversion between a data.domain.Sort (Spring JPA) Object to an OrderSpecifier (QueryDSL).

GIT Source of Querydsl Support in Spring JPA

It is really ugly implementation but you could still reuse it for your own purpose as the method is private:

public JPQLQuery applySorting(Sort sort, JPQLQuery query)

But if you use Spring data JPA, in your custom Repository implementation, you just need to do:

public Page<MyObject> findAll(Predicate predicate, Pageable pageable) {

    QMyObject myObject = QMyObject.myObject;
    JPQLQuery jPQLQuery = from(myObject)
            .join(myObject.user)
            .where(predicate);
    jPQLQuery = getQuerydsl().applyPagination(pageable, jPQLQuery);
    List<MyObject> myObjectList = jPQLQuery.list(myObject);
    long count =  jPQLQuery.count();
    Page<MyObject> myObjectPage = new PageImpl<MyObject>(myObjectList, pageable, count);
    return myObjectPage;  
}

Hope it could help!

Solution 3

org.springframework.data.domain.Sort.Order and com.querydsl.core.types.Order and are so similar, yet there is no straightforward conversion between the two. This is somewhat improved version of frozenfury answer:

PathBuilder<Entity> entityPath = new PathBuilder<>(Entity.class, "entity");
for (Order order : pageable.getSort()) {
    PathBuilder<Object> path = entityPath.get(order.getProperty());
    query.orderBy(new OrderSpecifier(com.querydsl.core.types.Order.valueOf(order.getDirection().name()), path));
}

Solution 4

private OrderSpecifier<?>[] getSortedColumn(Sort sorts){   
    return sorts.toList().stream().map(x ->{
        Order order = x.getDirection().name() == "ASC"? Order.ASC : Order.DESC;
        SimplePath<Object> filedPath = Expressions.path(Object.class, Qobject, x.getProperty());
        return new OrderSpecifier(order, filedPath);
    }).toArray(OrderSpecifier[]::new);
}

then you can use like this:

  .where(...), 
  .orderBy(getSortedColumn(pageable.getSort()))
Share:
23,942
beginner_
Author by

beginner_

Updated on February 12, 2021

Comments

  • beginner_
    beginner_ about 3 years

    This is basically the opposite of this: How to do a paged QueryDSL query with Spring JPA?

    This is for a custom query for which i can't use any of the findAll() methods.

    EDIT:

    Posted the wrong link. Now corrected.

  • beginner_
    beginner_ over 11 years
    marked as answer as my question was answered and I came to the same solution except using MyClass.class instead of Object.class. However how do i do this in a generic way, eg MyClass is actually <T extends MyClass>?
  • Timo Westkämper
    Timo Westkämper over 11 years
    You should reuse the orderByExpression, since it is a common parent for the order by children. Also the name is misleading, since the children are the actual "order by expressions".
  • Cenobyte321
    Cenobyte321 over 7 years
    This kind of works for my case, but not completely. The problem is that I need to sort calculated fields (sum, count). I have them as aliases but the problem is the PathBuilder always appends to the query "alias." + property. In the example it always returns "ORDER BY object.{alias}" which is invalid. How can I get QueryDSL to just append "ORDER BY {alias}" ?
  • wmakley
    wmakley almost 4 years
    This worked for me after some fiddling. Anyone know if it's secure?
  • Marinos An
    Marinos An over 3 years
    What is objectDTO?
  • Admin
    Admin over 3 years
    It means new Instance generated by Querydsl.
  • costaparas
    costaparas about 3 years
    The community encourages adding explanations alongisde code, rather than purely code-based answers (see here).