2008-09-23 9 views
46

Ich benutze Hibernate für ORM meiner Java-App zu einer Oracle-Datenbank (nicht, dass der Datenbankhersteller wichtig ist, können wir eines Tages zu einer anderen Datenbank wechseln), und ich möchte Objekte aus der Datenbank nach vom Benutzer bereitgestellten Strings. Wenn Sie zum Beispiel nach Personen suchen, wenn der Benutzer nach Leuten sucht, die in 'fran' leben, möchte ich in der Lage sein, ihren Leuten in San Francisco zu geben.Case-insensitive Suche mit Hibernate

SQL ist nicht meine starke Farbe, und ich bevorzuge Hibernate Criteria Bau-Code zu fest codierten Strings wie es ist. Kann mir jemand in die richtige Richtung weisen, wie man das im Code macht, und wenn unmöglich, wie sollte das hart codierte SQL aussehen?

Danke,

Yuval = 8-)

Antwort

67

Für den einfachen Fall, den Sie beschreiben, schauen Sie sich Restrictions.ilike() an, was eine Suche ohne Berücksichtigung der Groß- und Kleinschreibung durchführt.

Criteria crit = session.createCriteria(Person.class); 
crit.add(Restrictions.ilike('town', '%fran%'); 
List results = crit.list(); 
+0

Danke ... war nicht bewusst ilike existierte in Hibernate = 8-) – Yuval

+9

Und für alle auf der Suche nach dem NHibernate gleichwertigen Versuch 'InsensitiveLike()' –

+6

Ich habe es gerade ausprobiert. und es verhält sich nicht case-insensitiv –

0

Die meisten Standard-Datenbank-Sortierungen sind nicht case-sensitive, aber in der SQL Server-Welt kann es an der Instanz festgelegt werden, die Datenbank und Spaltenebene .

0

Sie könnten mit Compass eine Hülle über Lucene betrachten.

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

Durch ein paar Anmerkungen zu Ihrer Domain Hinzufügen von Objekten Sie diese Art der Sache bekommen erreichen.

Compass bietet eine einfache API für die Arbeit mit Lucene. Wenn Sie wissen, wie man ein ORM verwendet, dann werden Sie sich mit Compass mit einfachen Operationen für das Speichern und Löschen der & Abfrage wie zu Hause fühlen.

Von der Website selbst. "Auf Lucene aufbauend, vereinfacht Compass die allgemeinen Verwendungsmuster von Lucene, wie Google-Suche, Indexaktualisierungen sowie erweiterte Konzepte wie Caching und Indexsharting (Subindizes). Compass verwendet außerdem integrierte Optimierungen für gleichzeitige Commits und verschmilzt. "

Ich habe das in der Vergangenheit verwendet und finde es großartig.

3

Der übliche Ansatz zu Fall zu ignorieren, ist sowohl die Datenbankwerte und den Eingangswert auf Groß- oder Kleinbuchstaben zu umwandeln - die resultierende SQL etwas wie

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

In Hibernate Kriterien restrictions.like haben würde (..).. ignoreCase()

ich besser vertraut mit Nhibernate bin so die Syntax nicht 100% genau

für einige weitere Informationen zu sehen sein könnte pro hibernate 3 extract und hibernate docs 15.2. Narrowing the result set

+0

Für Hibernate Version 3.6.1 ist der Abschnitt zum Einschränken der Ergebnismenge 17.2. [Link] (http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#querycriteria-narrowing) – zmf

+0

Sir, beide Links sind nicht gültig. –

4

Sie müssen auch nicht die '%' Wildcards einfügen. Sie können MatchMode (docs for previous releases here) übergeben, um der Suche mitzuteilen, wie sie sich verhalten soll. START, ANYWHERE, EXACT und END Übereinstimmungen sind die Optionen.

9

Wenn verwenden Sie Spring HibernateTemplate mit Hibernate zu kommunizieren, sich hier, wie Sie auf einem Benutzer E-Mail-Adresse ein Groß- und Kleinschreibung Suche tun würde:

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

Dieser Kommentar hat wirklich geholfen, In meiner Anwendung habe ich Code wie folgt: 'Benutzer u = new User(); u.setUsername (Benutzername); Liste list = HibernateTemplate.findByExample () 'um den Benutzer aus der Datenbank zu finden. Aber das nimmt den Benutzernamen in dem Fall, dass ich es gebe. Aber ich wollte eine Abfrage schreiben, die die Suche ohne Berücksichtigung der Groß-/Kleinschreibung ausführt, also benutzte ich den Fund wie von SamS gezeigt: 'Liste list = HibernateTemplate.find (" von Benutzer wo ober (username) =? ", U.getUsername() .toUpperCase()); ' – amit

36
Criteria crit = session.createCriteria(Person.class); 
crit.add(Restrictions.ilike('town', 'fran', MatchMode.ANYWHERE); 
List results = crit.list(); 
0

Dies kann auch das Kriterium Beispiel für die Verwendung erfolgen, im org.hibernate.criterion-Paket.

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

Nur eine andere Möglichkeit, die ich oben genannten nützlich finde.