web-dev-qa-db-fra.com

Recherche insensible à la casse avec Hibernate

J'utilise Hibernate pour l'ORM de mon Java vers une base de données Oracle (pas que le fournisseur de la base de données compte, nous pourrons peut-être passer à une autre base de données un jour), et je souhaite récupérer des objets de la base de données en fonction des chaînes fournies par l'utilisateur. Par exemple, lors de la recherche de personnes, si l'utilisateur recherche des personnes qui vivent dans 'fran', je veux pouvoir donner son peuple à San Francisco.

SQL n'est pas mon point fort, et je préfère le code de construction Criteria d'Hibernate aux chaînes codées en dur. Quelqu'un peut-il m'orienter dans la bonne direction sur la façon de procéder dans le code et, si cela est impossible, à quoi devrait ressembler le code SQL codé en dur?

Merci,

Yuval = 8-)

48
Yuval

Pour le cas simple que vous décrivez, regardez Restrictions.ilike (), qui effectue une recherche non sensible à la casse.

Criteria crit = session.createCriteria(Person.class);
crit.add(Restrictions.ilike('town', '%fran%');
List results = crit.list();
71
Cowan
Criteria crit = session.createCriteria(Person.class);
crit.add(Restrictions.ilike('town', 'fran', MatchMode.ANYWHERE);
List results = crit.list();
37
vasile

Si vous utilisez HibernateTemplate de Spring pour interagir avec Hibernate, voici comment effectuer une recherche insensible à la casse sur l'adresse e-mail d'un utilisateur:

getHibernateTemplate().find("from User where upper(email)=?", emailAddr.toUpperCase());
9
SamS

L'approche habituelle pour ignorer la casse consiste à convertir les valeurs de la base de données et la valeur d'entrée en majuscules ou minuscules - le sql résultant aurait quelque chose comme

select f.name from f where TO_UPPER(f.name) like '%FRAN%'

Dans les critères d'hibernation restrictions.like (...). IgnoreCase ()

Je connais mieux Nhibernate donc la syntaxe n'est peut-être pas précise à 100%

pour plus d'informations, voir extrait pro hibernate et hibernate docs 15.2. Rétrécissement du jeu de résultats

4
Richard

Vous n'avez pas non plus à insérer les caractères génériques '%'. Vous pouvez passer MatchMode ( documents pour les versions précédentes ici ) pour indiquer à la recherche comment se comporter. START, ANYWHERE, EXACT et END correspondances sont les options.

4
Arthur Thomas

La plupart des classements de base de données par défaut ne respectent pas la casse, mais dans le monde SQL Server, ils peuvent être définis au niveau de l'instance, de la base de données et de la colonne.

0
Cade Roux

Vous pouvez envisager d'utiliser Compass un wrapper au-dessus de Lucene.

http://www.compass-project.org/

En ajoutant quelques annotations à vos objets de domaine, vous obtenez ce genre de chose.

Compass fournit une API simple pour travailler avec Lucene. Si vous savez comment utiliser un ORM, vous vous sentirez comme chez vous avec Compass avec des opérations simples pour enregistrer, supprimer et interroger.

Depuis le site lui-même. "S'appuyant sur Lucene, Compass simplifie les modèles d'utilisation courants de Lucene tels que la recherche de style Google, les mises à jour d'index ainsi que des concepts plus avancés tels que la mise en cache et le partage d'index (sous-index). Compass utilise également des optimisations intégrées pour les validations simultanées et fusionne. "

Je l'ai utilisé dans le passé et je le trouve génial.

0
Paul Whelan

Cela peut également être fait en utilisant le critère Example, dans le package 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();
}

Juste une autre façon que je trouve utile d'accomplir ce qui précède.

0
Casey