使用 Hibernate 进行不区分大小写的搜索
Posted
技术标签:
【中文标题】使用 Hibernate 进行不区分大小写的搜索【英文标题】:Case-insensitive search using Hibernate 【发布时间】:2010-09-12 08:16:47 【问题描述】:我正在使用 Hibernate 将我的 Java 应用程序的 ORM 用于 Oracle 数据库(不是数据库供应商很重要,我们可能有一天会切换到另一个数据库),我想根据用户提供的从数据库中检索对象字符串。例如,在搜索人员时,如果用户正在寻找住在“弗兰”的人,我希望能够给她在旧金山的人。
SQL 不是我的强项,我更喜欢 Hibernate 的 Criteria
构建代码而不是硬编码字符串。谁能指出我在代码中如何做到这一点的正确方向,如果不可能,硬编码的 SQL 应该是什么样子?
谢谢,
尤瓦尔=8-)
【问题讨论】:
【参考方案1】:对于您描述的简单情况,请查看 Restrictions.ilike(),它执行不区分大小写的搜索。
Criteria crit = session.createCriteria(Person.class);
crit.add(Restrictions.ilike('town', '%fran%');
List results = crit.list();
【讨论】:
谢谢...不知道 Hibernate 中存在 ilike =8-) 对于任何寻找 NHibernate 等效项的人,请尝试 'InsensitiveLike()' 我刚试过这个。并且它的行为不区分大小写 嗯...首选 MatchMode.ANYWHERE 而不是 '%' 请注意,如果您从 Eq 切换到 Like,您还将启用通配符,因此 oracle 中的下划线等匹配任何字符。【参考方案2】:Criteria crit = session.createCriteria(Person.class);
crit.add(Restrictions.ilike('town', 'fran', MatchMode.ANYWHERE);
List results = crit.list();
【讨论】:
MatchMode.ANYWHERE 有什么用?它将匹配字符串中任何位置的模式。但它也会提供不区分大小写的搜索。 (比如如果我搜索狮子 - 它也会显示狮子的结果)【参考方案3】:如果您使用 Spring 的 HibernateTemplate 与 Hibernate 进行交互,那么您将如何对用户的电子邮件地址进行不区分大小写的搜索:
getHibernateTemplate().find("from User where upper(email)=?", emailAddr.toUpperCase());
【讨论】:
这条评论真的很有帮助,在我的应用程序中,我的代码如下:User u = new User(); u.setUsername(username); List<User> list = HibernateTemplate.findByExample(<u>)
从数据库中查找用户。但在我给它的情况下,这是使用用户名。但我想编写一个执行不区分大小写搜索的查询,所以我使用了 SamS 所示的查找,如下所示:List<User> list = HibernateTemplate.find("from User where upper(username)=?", u.getUsername().toUpperCase());
【参考方案4】:
您也不必输入“%”通配符。你可以传入MatchMode (docs for previous releases here) 来告诉搜索如何表现。 START
、ANYWHERE
、EXACT
和 END
匹配是选项。
【讨论】:
【参考方案5】:忽略大小写的常用方法是将数据库值和输入值都转换为大写或小写 - 生成的 sql 会有类似
select f.name from f where TO_UPPER(f.name) like '%FRAN%'
在休眠条件限制.like(...).ignoreCase()
我更熟悉 Nhibernate,所以语法可能不是 100% 准确
有关更多信息,请参阅 pro hibernate 3 extract 和 hibernate docs 15.2. Narrowing the result set
【讨论】:
对于休眠版本 3.6.1,用于缩小结果集的部分是 17.2。 Link 先生,这两个链接都无效。【参考方案6】:这也可以使用 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();
这只是我认为对完成上述任务有用的另一种方式。
【讨论】:
【参考方案7】:自 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();
【讨论】:
【参考方案8】:大多数默认数据库排序规则不区分大小写,但在 SQL Server 世界中,它可以在实例、数据库和列级别进行设置。
【讨论】:
【参考方案9】:您可以查看在 lucene 之上使用 Compass 包装器。
http://www.compass-project.org/
通过向您的域对象添加一些注释,您可以实现此类目标。
Compass 为使用 Lucene 提供了一个简单的 API。如果您知道如何使用 ORM,那么您会对 Compass 感到宾至如归,只需简单的保存、删除和查询操作即可。
来自网站本身。 “在 Lucene 之上构建,Compass 简化了 Lucene 的常见使用模式,例如 google 风格的搜索、索引更新以及更高级的概念,例如缓存和索引分片(子索引)。Compass 还使用内置优化来实现并发提交和合并。”
我以前用过这个,感觉很棒。
【讨论】:
以上是关于使用 Hibernate 进行不区分大小写的搜索的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 htmx 在 django 中进行不区分大小写的主动搜索
NSPredicate 使用 CloudKit 进行不区分大小写的字符串搜索
IOS / Objective-C:使用StringByReplacingOccurrencesOfString进行不区分大小写搜索