Поиск с учетом регистра в критериях гибернации

Я использую 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 '',

Надеюсь, это поможет некоторым из вас.

Другие вопросы по тегам