Issue with getting query and parameters from GenericFilter

I found a possible bug in the provided bean QueryConditionProcessor:

The query is generated incorrectly when there are two data stores and a table from one store has a reference to a table in another store.

Generated query:

select e from Student e where e.room = :roommNYDXfvb

Parameters:

{roommNYDXfvb=019941e6-f9ee-7787-b543-aaee4cde11dc}

The parameter "roommNYDXfvb" is assigned the ID value instead of the Room entity.

It should be:

select e from Student e where e.room.id = :roommNYDXfvb

I have provided a test project that demonstrates this issue.

Reference information about QueryConditionProcessor on the forum:

Could you please advise on possible workarounds for this bug?

Jmix version: 2.6.1
IntelliJ IDEA 2025.2.1 (Ultimate Edition)

image
issueQueryConditionProcessor (2).zip (109.3 KB)

Hello,

Thank you for the demo project! I’ve debugged the problem and found the cause.

In general, QueryConditionProcessor works correctly. You just need to provide the entity name to the ConditionGenerationContext. Without the entityName, the ConditionJpqlGenerator cannot determine whether the property is a cross-data-store reference or not.

The bean with fix:

@Component
public class QueryConditionProcessor {
    public record QueryWithParameters(String query, Map<String, Object> parameters) {
    }
    private final ConditionJpqlGenerator conditionJpqlGenerator;
    private final ParameterJpqlGenerator parameterJpqlGenerator;

    public QueryConditionProcessor(ConditionJpqlGenerator conditionJpqlGenerator, ParameterJpqlGenerator parameterJpqlGenerator) {
        this.conditionJpqlGenerator = conditionJpqlGenerator;
        this.parameterJpqlGenerator = parameterJpqlGenerator;
    }

    public QueryWithParameters process(String query, Condition condition, String entityName) {
        Condition actualizedCondition = condition.actualize(Set.of(), true);
        if (actualizedCondition != null) {
            ConditionGenerationContext conditionGenerationContext = new ConditionGenerationContext(actualizedCondition);
            conditionGenerationContext.setEntityName(entityName); // set entity name
            String processedQuery = conditionJpqlGenerator.processQuery(query, conditionGenerationContext);
            
            Map<String, Object> parameters = new HashMap<>();
            parameterJpqlGenerator.processParameters(parameters, parameters, actualizedCondition, entityName);
            return new QueryWithParameters(processedQuery, parameters);
        } else {
            return new QueryWithParameters(query, Collections.emptyMap());
        }
    }
}
1 Like

Nice, many thanks for help!