简体   繁体   English

使用 Hibernate 进行不区分大小写的搜索

[英]Case-insensitive search using Hibernate

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.我正在将 Hibernate 用于我的 Java 应用程序到 Oracle 数据库的 ORM(不是数据库供应商很重要,我们可能有一天会切换到另一个数据库),我想根据用户提供的字符串从数据库中检索对象。 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.例如,在搜索人员时,如果用户正在寻找居住在“fran”的人员,我希望能够为她提供旧金山的人员。

SQL is not my strong suit, and I prefer Hibernate's Criteria building code to hard-coded strings as it is. SQL 不是我的强项,与硬编码字符串相比,我更喜欢 Hibernate 的Criteria构建代码。 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?任何人都可以指出我如何在代码中执行此操作的正确方向,如果不可能,硬编码的 SQL 应该是什么样子?

Thanks,谢谢,

Yuval =8-)尤瓦尔 =8-)

For the simple case you describe, look at Restrictions.ilike(), which does a case-insensitive search. 对于您描述的简单情况,请查看Restrictions.ilike(),它执行不区分大小写的搜索。

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

如果你使用Spring的HibernateTemplate与Hibernate进行交互,那么你可以在这里对用户的电子邮件地址进行不区分大小写的搜索:

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

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 忽略大小写的常用方法是将数据库值和输入值都转换为大写或小写 - 结果sql会有类似的东西

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

In hibernate criteria restrictions.like(...).ignoreCase() 在hibernate条件limits.like(...)。ignoreCase()

I'm more familiar with Nhibernate so the syntax might not be 100% accurate 我对Nhibernate更熟悉,因此语法可能不是100%准确

for some more info see pro hibernate 3 extract and hibernate docs 15.2. 有关更多信息,请参阅pro hibernate 3 extracthibernate docs 15.2。 Narrowing the result set 缩小结果集

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. 您可以通过MatchMode此处的先前版本的文档 )来告诉搜索如何操作。 START , ANYWHERE , EXACT , and END matches are the options. STARTANYWHEREEXACTEND匹配。

Since Hibernate 5.2 session.createCriteria is deprecated.由于 Hibernate 5.2 session.createCriteria已弃用。 Below is solution using JPA 2 CriteriaBuilder.以下是使用 JPA 2 CriteriaBuilder 的解决方案。 It uses like and upper :它使用likeupper

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

大多数默认数据库排序规则不区分大小写,但在SQL Server环境中,可以在实例,数据库和列级别设置它。

You could look at using Compass a wrapper above lucene. 你可以看看使用Compass上面的lucene包装器。

http://www.compass-project.org/ 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. Compass提供了一个与Lucene一起使用的简单API。 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. 如果您知道如何使用ORM,那么您可以在Compass的主页上使用简单的保存操作,删除和查询。

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." “构建于Lucene之上,Compass简化了Lucene的常见使用模式,例如谷歌式搜索,索引更新以及更高级的概念,如缓存和索引分片(子索引).Compass还使用内置优化进行并发提交和合并“。

I have used this in the past and I find it great. 我过去曾经用过这个,我发现它很棒。

This can also be done using the criterion Example, in the org.hibernate.criterion package. 这也可以使用org.hibernate.criterion包中的标准Example来完成。

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. 只是另一种我觉得有用的方法来实现上述目的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM