JPA Specification Order By Case with Select Distinct

37 views Asked by At

I am working on a JPA Specification where I need to order the results based on an Enum that is stored as a string in the database. The order of the Enum values is custom and not alphabetical. Here's the relevant part of my specification:

@Override
public Predicate toPredicate(Root<ItemEntity> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
    List<Order> orderList = getOrderList(root, query, criteriaBuilder);

    query.orderBy(orderList);
    query.distinct(true);

    return getPredicate();
}

The orderList is dynamically generated based on the ItemState enum values. The method to generate this order is as follows:

private Expression<Integer> getItemOrder(Root<MergeRequestEntity> root, CriteriaBuilder criteriaBuilder) {
    List<ItemState> itemStateOrderList = List.of(ItemState.QUEUED, ItemState.SHIPPED, ItemState.DELIVERED);
    Expression<Integer> itemStateOrder = criteriaBuilder.selectCase();
    for (int i = 0; i < itemStateOrderList.size(); i++) {
        itemStateOrder = ((CriteriaBuilder.Case<Integer>) itemStateOrder).when(
            criteriaBuilder.equal(root.get("itemState"), itemStateOrderList.get(i)),
            i
        );
    }
    itemStateOrder = ((CriteriaBuilder.Case<Integer>) itemStateOrder).otherwise(itemStateOrderList.size());

    return itemStateOrder;
}

However, when I use query.distinct(true) along with my custom order, I encounter the following error due to the ORDER BY expression not being part of the select list:

Caused by: org.postgresql.util.PSQLException: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list

I tried to include the order expression in the select list like this, but it did not resolve the issue:

Expression<Integer> itemStateOrder = getItemOrder(root, criteriaBuilder);
query.multiselect(root, itemStateOrder.alias("orderExpr"));

Additionally, I found that using query.groupBy(root.get("id")) removes duplicates and works, but I cannot use it due to a known bug with JPA when using groupBy with Pageable (GitHub issue).

Is there a way to include my ORDER BY expression in the select list or another method to remove duplicates without encountering these issues?

0

There are 0 answers