4

我有一个使用 PostgreSQL 9.X 和 JPA2(Hibernate 实现)的 Java EE 项目。如何强制类似查询不区分大小写和不区分重音?

我能够更改数据库的字符集,因为它是第一个使用它的项目。

4

3 回答 3

5

一般来说,没有标准的方法来编写“不区分重音”的代码,或者在忽略重音的同时比较单词是否相等。整个想法几乎没有意义,因为不同的重音字符在不同的语言/方言中意味着不同的东西,并且它们的“普通 ascii”替换/扩展因语言而异。请不要这样做;resumerésumé不同的词,当考虑英语以外的任何语言时,情况会变得更糟。

对于不区分大小写,您可以lower(the_col) like lower('%match_expression')在 JPQL 中使用。据我所知ilike,JPQL 不支持,但我没有检查标准来验证这一点。它相当易读,因此请考虑下载 JPA2 规范并阅读它。JPA2 CriteriaRestrictions.ilike为此目的提供。两者都不会规范化/剥离/忽略重音字符。

对于去除重音等,您可能需要使用数据库引擎特定的存储函数或本机查询。参见,例如这个先前的答案,或者如果你打算用一个不带重音的替代品替换这个PostgreSQL wiki 条目- 但同样,请不要这样做,除非是为了非常有限的目的,比如查找单词可能是“不带重音”的地方被误导的软件或用户。

于 2012-10-23T09:06:44.580 回答
2

如果安装了unaccent 扩展

select unaccent(lower('ãóÊ'));
 unaccent 
----------
 aoe
于 2012-10-23T13:07:16.147 回答
0

我遇到了这个问题,我无法使用数据库功能。因此,我在标准代码中使用了 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;
}
于 2015-08-10T16:28:11.450 回答