我有一个使用 PostgreSQL 9.X 和 JPA2(Hibernate 实现)的 Java EE 项目。如何强制类似查询不区分大小写和不区分重音?
我能够更改数据库的字符集,因为它是第一个使用它的项目。
我有一个使用 PostgreSQL 9.X 和 JPA2(Hibernate 实现)的 Java EE 项目。如何强制类似查询不区分大小写和不区分重音?
我能够更改数据库的字符集,因为它是第一个使用它的项目。
一般来说,没有标准的方法来编写“不区分重音”的代码,或者在忽略重音的同时比较单词是否相等。整个想法几乎没有意义,因为不同的重音字符在不同的语言/方言中意味着不同的东西,并且它们的“普通 ascii”替换/扩展因语言而异。请不要这样做;resume
和résumé
是不同的词,当考虑英语以外的任何语言时,情况会变得更糟。
对于不区分大小写,您可以lower(the_col) like lower('%match_expression')
在 JPQL 中使用。据我所知ilike
,JPQL 不支持,但我没有检查标准来验证这一点。它相当易读,因此请考虑下载 JPA2 规范并阅读它。JPA2 CriteriaRestrictions.ilike
为此目的提供。两者都不会规范化/剥离/忽略重音字符。
对于去除重音等,您可能需要使用数据库引擎特定的存储函数或本机查询。参见,例如这个先前的答案,或者如果你打算用一个不带重音的替代品替换这个PostgreSQL wiki 条目- 但同样,请不要这样做,除非是为了非常有限的目的,比如查找单词可能是“不带重音”的地方被误导的软件或用户。
如果安装了unaccent 扩展:
select unaccent(lower('ãóÊ'));
unaccent
----------
aoe
我遇到了这个问题,我无法使用数据库功能。因此,我在标准代码中使用了 REGEX 限制:
searchText = unaccent(searchText);
String expression = "firstName ~* '.*" + searchText + ".*'";
Criterion searchCriteria = Restrictions.sqlRestriction(expression);
然后我编写了一个名为 unaccent 的函数来将每个字符更改为一个或语句,例如任何字母 e 将变为 (e|é|è)。对“hello”的查询将变为“h(e|é|è)llo”。
这是从这个线程启发的函数Postgres 重音不敏感 LIKE search in Rails 3.1 on Heroku
private String unaccent(String text) {
String String charactersProcessed = ""; // To avoid doing a replace multiple times.
String newText = text.toLowerCase();
text = newText; // Case statement is expecting lowercase.
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (charactersProcessed.contains(c + "")) {
continue; // We have already processed this character.
}
String replacement = "";
switch (c) {
case '1': {
replacement = "¹";
break;
}
case '2': {
replacement = "²";
break;
}
case '3': {
replacement = "³";
break;
}
case 'a': {
replacement = "á|à|â|ã|ä|å|ā|ă|ą|À|Á|Â|Ã|Ä|Å|Ā|Ă|Ą|Æ";
break;
}
case 'c': {
replacement = "ć|č|ç|©|Ć|Č|Ç";
break;
}
case 'd': {
replacement = "Đ|Ð";
break;
}
case 'e': {
replacement = "è|é|ê|ё|ë|ē|ĕ|ė|ę|ě|È|Ê|Ë|Ё|Ē|Ĕ|Ė|Ę|Ě|€";
break;
}
case 'g': {
replacement = "ğ|Ğ";
break;
}
case 'i': {
replacement = "ı|ì|í|î|ï|ì|ĩ|ī|ĭ|Ì|Í|Î|Ï|Ї|Ì|Ĩ|Ī|Ĭ";
break;
}
case 'l': {
replacement = "ł|Ł";
break;
}
case 'n': {
replacement = "ń|ň|ñ|Ń|Ň|Ñ";
break;
}
case 'o': {
replacement = "ò|ó|ô|õ|ö|ō|ŏ|ő|ø|Ò|Ó|Ô|Õ|Ö|Ō|Ŏ|Ő|Ø|Œ";
break;
}
case 'r': {
replacement = "ř|®|Ř";
break;
}
case 's': {
replacement = "š|ş|ș|ß|Š|Ş|Ș";
break;
}
case 'u': {
replacement = "ù|ú|û|ü|ũ|ū|ŭ|ů|Ù|Ú|Û|Ü|Ũ|Ū|Ŭ|Ů";
break;
}
case 'y': {
replacement = "ý|ÿ|Ý|Ÿ";
break;
}
case 'z': {
replacement = "ž|ż|ź|Ž|Ż|Ź";
break;
}
}
if (!replacement.isEmpty()) {
charactersProcessed = charactersProcessed + c;
newText = newText.replace(c + "", "(" + c + "|" + replacement + ")");
}
}
return newText;
}