Search code examples
javaquerydsl

QueryDSL Order by calculated field


In our application we use querydsl to fetch entities and transform them to a presentation object. This presentation object has field called active. This is decided by whether a certain date of the entity is before today (active = false) or after today (active = true). All goes well doing this. The problem is when trying to order by that expression (QEntity.someDate > today). Which makes hibernate throw this error:

org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected AST node: > near line 3, column 40 [select object.someField as someAlias, (object.someDate > ?1) as active, object as objectAlias
from com.example.Object object
order by object.someDate > ?1 asc]

I create the OrderSpecifier as follows:

    @Override
    public OrderSpecifier<?> getOrderByClause(SortKey sortKey) {
        BooleanExpression expression = getBooleanPath(); // This is the expression: (object.someDate > ?1)
        if (sortKey.getSortOrder() == ESortOrder.ASCENDING) {
            return new OrderSpecifier(Order.ASC, expression);
        }
        return new OrderSpecifier(Order.DESC, expression);
    }

I also tried it like this:

    @Override
    public OrderSpecifier<?> getOrderByClause(SortKey sortKey) {
        BooleanExpression expression = getBooleanPath();
        if (sortKey.getSortOrder() == ESortOrder.ASCENDING) {
            return new CaseBuilder().when(expression.isFalse()).then(1).otherwise(2).asc();
        }
        return new CaseBuilder().when(expression.isTrue()).then(1).otherwise(2).desc();
    }

Which results in a similar error:

org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected AST node: > near line 3, column 40 [select object.someField as someAlias, (object.someDate > ?1) as active, object as objectAlias
from com.example.Object object
order by case when (object.someDate > ?1 = ?2) then ?3 else 2 end asc]

And finally like this:

    @Override
    public OrderSpecifier<?> getOrderByClause(SortKey sortKey) {
        BooleanExpression expression = getBooleanPath();
        if (sortKey.getSortOrder() == ESortOrder.ASCENDING) {
            return new CaseBuilder().when(expression.eq(true)).then(1).otherwise(2).asc();
        }
        return new CaseBuilder().when(expression.eq(true)).then(1).otherwise(2).desc();
    }

Which throws the same error as the previous


Solution

  • Fixed it by creating the order clause like this:

        @Override
        public OrderSpecifier<?> getOrderByClause(SortKey sortKey) {
            BooleanPath path = getBooleanPath();
            if (sortKey.getSortOrder() == ESortOrder.ASCENDING) {
                return path.asc();
            }
            return path.desc();
        }
    
        private BooleanPath getBooleanPath() {
            return Expressions.booleanPath(getFieldName());
        }
    

    Where field name is the alias as string, in our case "active".