Case-insensitive search using Hibernate

三世轮回 提交于 2019-12-03 02:57:30

问题


I'm using Hibernate for ORM of my Java app to an Oracle database (not that the database vendor matters, we may switch to another database one day), and I want to retrieve objects from the database according to user-provided strings. For example, when searching for people, if the user is looking for people who live in 'fran', I want to be able to give her people in San Francisco.

SQL is not my strong suit, and I prefer Hibernate's Criteria building code to hard-coded strings as it is. Can anyone point me in the right direction about how to do this in code, and if impossible, how the hard-coded SQL should look like?

Thanks,

Yuval =8-)


回答1:


For the simple case you describe, look at Restrictions.ilike(), which does a case-insensitive search.

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:


If you use Spring's HibernateTemplate to interact with Hibernate, here is how you would do a case insensitive search on a user's email address:

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



回答4:


You also do not have to put in the '%' wildcards. You can pass MatchMode (docs for previous releases here) in to tell the search how to behave. START, ANYWHERE, EXACT, and END matches are the options.




回答5:


The usual approach to ignoring case is to convert both the database values and the input value to upper or lower case - the resultant sql would have something like

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

In hibernate criteria restrictions.like(...).ignoreCase()

I'm more familiar with Nhibernate so the syntax might not be 100% accurate

for some more info see pro hibernate 3 extract and hibernate docs 15.2. Narrowing the result set




回答6:


Most default database collations are not case-sensitive, but in the SQL Server world it can be set at the instance, the database, and the column level.




回答7:


You could look at using Compass a wrapper above lucene.

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

By adding a few annotations to your domain objects you get achieve this kind of thing.

Compass provides a simple API for working with Lucene. If you know how to use an ORM, then you will feel right at home with Compass with simple operations for save, and delete & query.

From the site itself. "Building on top of Lucene, Compass simplifies common usage patterns of Lucene such as google-style search, index updates as well as more advanced concepts such as caching and index sharding (sub indexes). Compass also uses built in optimizations for concurrent commits and merges."

I have used this in the past and I find it great.




回答8:


This can also be done using the criterion Example, in the org.hibernate.criterion package.

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

Just another way that I find useful to accomplish the above.




回答9:


Since Hibernate 5.2 session.createCriteria is deprecated. Below is solution using JPA 2 CriteriaBuilder. It uses like and 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();


来源:https://stackoverflow.com/questions/120588/case-insensitive-search-using-hibernate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!