Поиск с учетом регистра в критериях гибернации
Я использую Hibernate 3 с SQL Server 2008. Я хочу выполнять поиск с учетом регистра в Hibernate Criteria. Я не могу этого достичь. Мой код, как показано ниже:
Criteria criteria = session.createCriteria(User.class); /*line 1*/
criteria.add(Restrictions.eq("userName", userName)); /*line 2*/
У меня есть класс User.java, который содержит String userName
,
Записи в БД:
id | user_name
--------------
1 | abc
2 | xyz
Теперь, если я пройду "abc"
как userName
в строке 2 он должен вернуть первую запись из БД. Но если я пройду "Abc"
, "ABC"
, "aBC"
и т. д. как userName
в строке 2 записи не должны выбираться.
Я посетил эту ссылку, но она мне не нужна, так как я не хочу использовать параметры сортировки с hql или с SQL Server. Я открыт для использования сопоставления с Criteria
но не знаю как это сделать.
6 ответов
Criteria criteria = s.createCriteria(User.class);
criteria.add(
Expression.sql("userName = ? collate Latin1_General_CS_AS_KS_WS", userName, new StringType())
);
Вы не можете с Hibernate. Проблема в MS SQL - по умолчанию используется сортировка без учета регистра. Там может быть два обходных пути:
1 Выберите с помощью Hibernate и выполните программную фильтрацию результатов.
2 При создании таблицы используйте сортировку с учетом регистра для файла, вам необходимо выполнить поиск: COLLATE SQL_Latin1_General_CP850_BIN2 или другое значение, указанное для вашего сервера (прочитано из SYSTEMPROPERTY).
Вы можете попробовать это (используя ilike в API ограничений)
Criteria criteria = s.createCriteria(User.class);
criteria.add(Restrictions.ilike("userName", userName));
С уважением
Если вы выберете маршрут sql, у вас возникнут проблемы со ссылкой на псевдоним в другом запросе HQL / Criterion. Все, что требуется, - это создать подкласс LikeExpression или что-то еще и предоставить свой собственный метод toSqlString(). Протестировано в MySql.
private static class CaseSensitiveLike extends LikeExpression {
protected CaseSensitiveLike(final String propertyName,
final String value, final MatchMode mode) {
super(propertyName, value, mode);
}
@Override
public String toSqlString(final Criteria criteria,
final CriteriaQuery criteriaQuery) {
String sql = super.toSqlString(criteria, criteriaQuery);
return sql + " collate utf8_bin";
}
}
и тогда следующие вызовы взаимозаменяемы:
Criterion insensitive = Restrictions.like(myProperty, myValue, MatchMode.ANYWHERE);
Criterion sensitive = new CaseSensitiveLike(ldProperty, value, MatchMode.ANYWHERE);
Это может не подходить для вас, но может быть лучше использовать lucene/solr для такого рода запросов. В дополнение к нечувствительным к регистру запросам он будет обрабатывать и другие распространенные для вас сценарии.
Я добавил ту же проблему и изменил тип сортировки в таблице базы данных прямо на сервере mariadb.
Я создаю поле таблицы с "COLLATE latin1_general_cs"
Поэтому каждый поиск в этом поле будет чувствительным к регистру.
Поле моей таблицы выглядит следующим образом.
'case_sensitive_key' varchar (255) CHARACTER SET latin1 COLLATE latin1_general_cs NOT NULL DEFAULT '',
Надеюсь, это поможет некоторым из вас.