Reputation: 4867
i'd like to select items case insensitive with an In-Criterion with Hibernate Criteria API. E.g.
Criteria crit = session.createCriteria(Item.class);
crit.add(Restrictions.in("prop", valueList).ignoreCase());
Unfortunately the Criterion class doesn't has an ignoreCase method. HQL is not an alternative.
Upvotes: 4
Views: 6624
Reputation: 1
.add(Restrictions.sqlRestriction("upper({alias}.COLUMN_NAME) = upper(?)", VALUE_TO_COMPARE, Hibernate.STRING))
worked for me.
Upvotes: 0
Reputation: 992
An alternative will be to use an sqlRestriction. So you convert your values to comma-separated lower case strings and thereafter you call.
crit.add(Restrictions.sqlRestriction("lower({alias}.prop) in ( " + q + " )"));
However your query parameters will have to be sanitized.
You could also use disjunction.
Junction j = Restrictions.disjunction();
for (String prop: props) {
j.add(Restrictions.eq("prop", prop).ignoreCase());
}
crit.add(j);
Upvotes: 3
Reputation: 4867
I implemented my own InExpression which ignores case. It is almost the same as InExpresion from hibernate-core-3.6.10.Final. Only differences are the 'lower(..)'.
import java.util.ArrayList;
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.criterion.CriteriaQuery;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.InExpression;
import org.hibernate.engine.TypedValue;
import org.hibernate.type.CompositeType;
import org.hibernate.type.Type;
import org.hibernate.util.StringHelper;
public class InExpressionIgnoringCase implements Criterion {
private final String propertyName;
private final Object[] values;
public InExpressionIgnoringCase(final String propertyName, final Object[] values) {
this.propertyName = propertyName;
this.values = values;
}
public String toSqlString(final Criteria criteria, final CriteriaQuery criteriaQuery) throws HibernateException {
final String[] columns = criteriaQuery.findColumns(this.propertyName, criteria);
final String[] wrappedLowerColumns = wrapLower(columns);
if (criteriaQuery.getFactory().getDialect().supportsRowValueConstructorSyntaxInInList() || columns.length <= 1) {
String singleValueParam = StringHelper.repeat("lower(?), ", columns.length - 1) + "lower(?)";
if (columns.length > 1)
singleValueParam = '(' + singleValueParam + ')';
final String params = this.values.length > 0 ? StringHelper.repeat(singleValueParam + ", ",
this.values.length - 1) + singleValueParam : "";
String cols = StringHelper.join(", ", wrappedLowerColumns);
if (columns.length > 1)
cols = '(' + cols + ')';
return cols + " in (" + params + ')';
} else {
String cols = " ( " + StringHelper.join(" = lower(?) and ", wrappedLowerColumns) + "= lower(?) ) ";
cols = this.values.length > 0 ? StringHelper.repeat(cols + "or ", this.values.length - 1) + cols : "";
cols = " ( " + cols + " ) ";
return cols;
}
}
public TypedValue[] getTypedValues(final Criteria criteria, final CriteriaQuery criteriaQuery)
throws HibernateException {
final ArrayList<TypedValue> list = new ArrayList<TypedValue>();
final Type type = criteriaQuery.getTypeUsingProjection(criteria, this.propertyName);
if (type.isComponentType()) {
final CompositeType actype = (CompositeType) type;
final Type[] types = actype.getSubtypes();
for (int j = 0; j < this.values.length; j++) {
for (int i = 0; i < types.length; i++) {
final Object subval = this.values[j] == null ? null : actype.getPropertyValues(this.values[j],
EntityMode.POJO)[i];
list.add(new TypedValue(types[i], subval, EntityMode.POJO));
}
}
} else {
for (int j = 0; j < this.values.length; j++) {
list.add(new TypedValue(type, this.values[j], EntityMode.POJO));
}
}
return list.toArray(new TypedValue[list.size()]);
}
@Override
public String toString() {
return this.propertyName + " in (" + StringHelper.toString(this.values) + ')';
}
private String[] wrapLower(final String[] columns) {
final String[] wrappedColumns = new String[columns.length];
for (int i = 0; i < columns.length; i++) {
wrappedColumns[i] = "lower(" + columns[i] + ")";
}
return wrappedColumns;
}
}
Usage:
final Criteria crit = session.createCriteria(Item.class);
crit.add(new InExpressionIgnoringCase("prop", array));
Upvotes: 4
Reputation: 691715
Get the source code of the Criterion class returned by Restrictions.in()
(InExpression
), and create another one which is similar but transforms all the elements of the value list to lowercase, and generates a SQL query like:
lower(prop) in (...)
Upvotes: 5