Really dynamic JPA CriteriaBuilder

You can pass an array of predicates to the CriteriaBuilder, deciding on equal or like as you go. For this, build a list and pack the contents of the list into an array in a single and statement. Like this:

final List<Predicate> predicates = new ArrayList<Predicate>();

for (final Entry<String, String> e : myPredicateMap.entrySet()) {

    final String key = e.getKey();
    final String value = e.getValue();

    if ((key != null) && (value != null)) {

        if (value.contains("%")) {
            predicates.add(criteriaBuilder.like(root.<String> get(key), value));
        } else {
            predicates.add(criteriaBuilder.equal(root.get(key), value));
        }
    }
}

query.where(criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()])));
query.select(count);

In case you need to distingiush between and and or, use two lists.


One option is to use the fact that method with variable number of arguments can take an array:

query.where(predicates.toArray(new Predicate[predicates.size()])); 

Alternatively, you can combine them into a single predicate (note that if you don't do it, you don't need to create a conjunction as in your example);:

Predicate where = cb.conjunction();
while (column.hasNext()) {
    ...
    where = cb.and(where, cb.equal(userRoot.get(colIndex), colValue));
}

query.where(where);