使用hibernate标准,是否可以转义特殊字符?

对于此问题,我们希望避免编写特殊查询,因为该查询在多个数据库中必须有所不同。仅希望使用hibernate条件,我们希望能够转义特殊字符。

这种情况是需要转义特殊字符的原因:

假设我们在数据库中有表“ foo”。表’foo’仅包含1个字段,称为’name’。“名称”字段可以包含在数据库中可能被认为是特殊字符。此名称的两个示例是“

name_1”和“ name%1”。至少在Oracle中,“

_”和“%”都是特殊字符。如果用户想要在将这些示例输入数据库后搜索其中一个示例,则可能会出现问题。

criterion = Restrictions.ilike("name", searchValue, MatchMode.ANYWHERE);

return findByCriteria(null, criterion);

在此代码中,“ searchValue”是用户已授予应用程序用于其搜索的值。如果用户要搜索“%”,则将返回数据库中的每个“

foo”条目。这是因为’%’字符表示用于字符串匹配的“任意数量的字符”通配符,并且hibernate生成的SQL代码如下所示:

select * from foo where name like '%'

有没有办法告诉hibernate的转义某些字符,或创建不是数据库类型特定的解决方法?

回答:

LikeExpression的构造函数均受保护,因此这不是一个可行的选择。同样,它也有自己的问题。

我和一位同事创建了一个效果很好的补丁。补丁的要点是,对于使用MatchMode的LikeExpression构造函数,我们转义了特殊字符。对于使用Character(转义字符)的构造函数,我们假设用户自己转义了特殊字符。

我们还参数化了转义字符,以确保它们使用\或引号字符之类的字符时不会破坏SQL查询。

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;

}

}

如果您想知道lhs和typedValue方法的用途,新的IlikeExpression应该回答这些问题。

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();

}

}

此后,剩下的唯一事情就是使Restrictions使用以下新类:

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

}

编辑:哦,是的。这适用于Oracle。但是,我们不确定其他数据库。

以上是 使用hibernate标准,是否可以转义特殊字符? 的全部内容, 来源链接: utcz.com/qa/426815.html

回到顶部