2012-07-18 86 views
4

我想选择与In-Criterion和Hibernate Criteria API不区分大小写的项目。 例如Ignorecase for In Criterion

Criteria crit = session.createCriteria(Item.class); 
crit.add(Restrictions.in("prop", valueList).ignoreCase()); 

不幸的是Criterion类没有ignoreCase方法。 HQL不是一种替代方案。

回答

5

Restrictions.in()InExpression)返回的标准类的源代码,并创建另一个是类似的,但变换值列表为小写的所有元素,并产生像SQL查询:

lower(prop) in (...) 
2

我实现了我自己的InExpression,它忽略了大小写。 它与hibernate-core-3.6.10.Final中的InExpresion几乎相同。 唯一的区别是'下(..)'。

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; 
} 
} 

用法:

final Criteria crit = session.createCriteria(Item.class); 
      crit.add(new InExpressionIgnoringCase("prop", array)); 
2

替代的方法是使用一个sqlRestriction。因此,您可以将您的值转换为逗号分隔的小写字符串,然后再调用。

crit.add(Restrictions.sqlRestriction("lower({alias}.prop) in (" + q + ")")); 

但是,您的查询参数将不得不进行消毒。可以使用disjunction

Junction j = Restrictions.disjunction(); 
for (String prop: props) { 
    j.add(Restrictions.eq("prop", prop).ignoreCase()); 
} 
crit.add(j); 
0
 .add(Restrictions.sqlRestriction("upper({alias}.COLUMN_NAME) = upper(?)", VALUE_TO_COMPARE, Hibernate.STRING)) 

为我工作。