Нечувствительный к регистру поиск с использованием Hibernate
Я использую Hibernate для ORM моего приложения Java в базе данных Oracle (не то, что имеет дело с производителем базы данных, мы можем переключиться на другую базу данных в один прекрасный день), и я хочу получить объекты из базы данных в соответствии с предоставленными пользователем строки. Например, при поиске людей, если пользователь ищет людей, которые живут в "fran", я хочу иметь возможность дать ее людям в Сан-Франциско.
SQL не мой сильный костюм, и я предпочитаю Hibernate Criteria
код здания для жестко закодированных строк, как есть. Может ли кто-нибудь указать мне в правильном направлении, как это сделать в коде, и если это невозможно, как выглядит жесткий код SQL?
Спасибо,
Yuval = 8 -)
Ответы
Ответ 1
В простом случае, который вы описываете, посмотрите на Restrictions.ilike(), который делает поиск без учета регистра.
Criteria crit = session.createCriteria(Person.class);
crit.add(Restrictions.ilike('town', '%fran%');
List results = crit.list();
Ответ 2
Criteria crit = session.createCriteria(Person.class);
crit.add(Restrictions.ilike('town', 'fran', MatchMode.ANYWHERE);
List results = crit.list();
Ответ 3
Если вы используете Spring HibernateTemplate для взаимодействия с Hibernate, вот как вы будете делать поиск без учета регистра на адрес электронной почты пользователя:
getHibernateTemplate().find("from User where upper(email)=?", emailAddr.toUpperCase());
Ответ 4
Обычный подход к игнорированию случая - это преобразование значений базы данных и входного значения в верхний или нижний регистр - результирующий sql будет иметь что-то вроде
select f.name from f where TO_UPPER(f.name) like '%FRAN%'
В спящих критериях ограничений .like(...). ignoreCase()
Я больше знаком с Nhibernate, поэтому синтаксис может быть не точным на 100%
для получения дополнительной информации см. pro hibernate 3 extract и спящий режим docs 15.2. Сужение набора результатов
Ответ 5
Вам также не нужно вводить подстановочные знаки%. Вы можете передать MatchMode (документы для предыдущих выпусков здесь), чтобы указать, как вести себя. START
, ANYWHERE
, EXACT
и END
соответствуют параметры.
Ответ 6
Большинство сопоставлений базы данных по умолчанию не чувствительны к регистру, но в мире SQL Server его можно установить в экземпляре, базе данных и уровне столбца.
Ответ 7
Вы можете посмотреть, как использовать компас с оболочкой над lucene.
http://www.compass-project.org/
Добавив несколько аннотаций к объектам домена, вы достигнете такого уровня.
Compass предоставляет простой API для работы с Lucene. Если вы знаете, как использовать ORM, тогда вы будете чувствовать себя как дома с помощью Compass с простыми операциями для сохранения и удаления и запроса.
С самого сайта.
"Основываясь на вершине Lucene, Compass упрощает общие шаблоны использования Lucene, такие как поиск в стиле Google, индексы, а также более продвинутые концепции, такие как кеширование и индексирование (sub indexs). Compass также использует встроенные оптимизации для параллельных коммитов и слияния".
Я использовал это в прошлом, и я нахожу это замечательным.
Ответ 8
Это также можно сделать, используя критерий Example, в пакете org.hibernate.criterion.
public List findLike(Object entity, MatchMode matchMode) {
Example example = Example.create(entity);
example.enableLike(matchMode);
example.ignoreCase();
return getSession().createCriteria(entity.getClass()).add(
example).list();
}
Еще один способ, которым я считаю полезным выполнить вышеизложенное.
Ответ 9
Начиная с Hibernate 5.2 session.createCriteria
устарела. Ниже приведено решение с использованием JPA 2 CriteriaBuilder. Он использует like
и upper
:
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
Root<Person> root = criteria.from(Person.class);
Expression<String> upper = builder.upper(root.get("town"));
criteria.where(builder.like(upper, "%FRAN%"));
session.createQuery(criteria.select(root)).getResultList();