Les constructeurs de LikeExpression sont tous protégés, donc ce n'est pas une option viable. En outre, il a problems of its own.
Un collègue et moi avons créé un patch qui fonctionne plutôt bien. L'essentiel du patch est que pour le constructeur LikeExpression qui consomme un MatchMode, nous échappons aux caractères spéciaux. Pour le constructeur qui consomme un caractère (le caractère d'échappement), nous supposons que l'utilisateur échappe lui-même les caractères spéciaux.
Nous avons également paramétré le caractère d'échappement pour s'assurer qu'il ne peut pas corrompre la requête SQL s'ils utilisent quelque chose comme \ ou un guillemet.
package org.hibernate.criterion;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.TypedValue;
public class LikeExpression implements Criterion {
private final String propertyName;
private final String value;
private final Character escapeChar;
protected LikeExpression(
String propertyName,
Object value) {
this(propertyName, value.toString(), (Character) null);
}
protected LikeExpression(
String propertyName,
String value,
MatchMode matchMode) {
this(propertyName, matchMode.toMatchString(value
.toString()
.replaceAll("!", "!!")
.replaceAll("%", "!%")
.replaceAll("_", "!_")), '!');
}
protected LikeExpression(
String propertyName,
String value,
Character escapeChar) {
this.propertyName = propertyName;
this.value = value;
this.escapeChar = escapeChar;
}
public String toSqlString(
Criteria criteria,
CriteriaQuery criteriaQuery) throws HibernateException {
Dialect dialect = criteriaQuery.getFactory().getDialect();
String[] columns = criteriaQuery.getColumnsUsingProjection(criteria, propertyName);
if (columns.length != 1) {
throw new HibernateException("Like may only be used with single-column properties");
}
String lhs = lhs(dialect, columns[0]);
return lhs + " like ?" + (escapeChar == null ? "" : " escape ?");
}
public TypedValue[] getTypedValues(
Criteria criteria,
CriteriaQuery criteriaQuery) throws HibernateException {
return new TypedValue[] {
criteriaQuery.getTypedValue(criteria, propertyName, typedValue(value)),
criteriaQuery.getTypedValue(criteria, propertyName, escapeChar.toString())
};
}
protected String lhs(Dialect dialect, String column) {
return column;
}
protected String typedValue(String value) {
return value;
}
}
Si vous vous demandez ce que les LHS et les méthodes TypedValue sont pour, la nouvelle IlikeExpression devrait répondre à ces questions.
package org.hibernate.criterion;
import org.hibernate.dialect.Dialect;
public class IlikeExpression extends LikeExpression {
protected IlikeExpression(
String propertyName,
Object value) {
super(propertyName, value);
}
protected IlikeExpression(
String propertyName,
String value,
MatchMode matchMode) {
super(propertyName, value, matchMode);
}
protected IlikeExpression(
String propertyName,
String value,
Character escapeChar) {
super(propertyName, value, escapeChar);
}
@Override
protected String lhs(Dialect dialect, String column) {
return dialect.getLowercaseFunction() + '(' + column + ')';
}
@Override
protected String typedValue(String value) {
return super.typedValue(value).toLowerCase();
}
}
Après cela, la seule chose qui reste est de faire restrictions utiliser ces nouvelles classes:
public static Criterion like(String propertyName, Object value) {
return new LikeExpression(propertyName, value);
}
public static Criterion like(String propertyName, String value, MatchMode matchMode) {
return new LikeExpression(propertyName, value, matchMode);
}
public static Criterion like(String propertyName, String value, Character escapeChar) {
return new LikeExpression(propertyName, value, escapeChar);
}
public static Criterion ilike(String propertyName, Object value) {
return new IlikeExpression(propertyName, value);
}
public static Criterion ilike(String propertyName, String value, MatchMode matchMode) {
return new IlikeExpression(propertyName, value, matchMode);
}
public static Criterion ilike(String propertyName, String value, Character escapeChar) {
return new IlikeExpression(propertyName, value, escapeChar);
}
Edit: Oh oui. Cela fonctionne pour Oracle. Cependant, nous ne sommes pas sûrs des autres bases de données.
Merci. J'espère pouvoir trouver le temps d'essayer ça plus tard aujourd'hui. Je vais mettre à jour après l'avoir essayé. –
IlikeExpression ne l'a pas cependant. –
Tous les constructeurs de LikeExpression sont protégés, vous devez sous-classer et créer un constructeur public. – EkcenierK