omnifaces / omnipersistence

Utilities for JPA, JDBC and DataSources
Other
31 stars 12 forks source link

Filtering on wrapped aggregated fields not possible #28

Closed Edubits closed 5 years ago

Edubits commented 5 years ago

When using a mapping like the following:

LinkedHashMap<Getter<YourEntityDTO>, Expression<?>> mapping = new LinkedHashMap<>();
mapping.put(YourEntityDTO::getId, root.get("id"));
mapping.put(YourEntityDTO::isFree, builder.equal(builder.sum(child.get("price"), 0));

it's not detected as an aggregation when adding a filter on the isFree field. The filter will be rendered as a WHERE clause, while it should be HAVING.

Edubits commented 5 years ago

As a workaround I have overriden Provider.HIBERNATE.isAggregation as follows:

@Override
public boolean isAggregation(Expression<?> expression) {
    return (HIBERNATE_BASIC_FUNCTION_EXPRESSION.get().isInstance(expression) && (boolean) invokeMethod(expression, "isAggregation"))
            || (
                    findClass("org.hibernate.query.criteria.internal.predicate.ComparisonPredicate").get().isInstance(expression) &&
                            (
                                    isAggregation(invokeMethod(expression, "getLeftHandOperand"))
                                            || isAggregation(invokeMethod(expression, "getRightHandOperand"))
                            )
    );
}

This adds support for (nested) comparisons where either the left or righthandside of the operation is a aggregation.

BalusC commented 5 years ago

Fixed, thanks for workaround hint.

Might only need to check this use case as well for EclipseLink and OpenJPA.