首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >JPA2:大小写不敏感,就像任何地方的匹配

JPA2:大小写不敏感,就像任何地方的匹配
EN

Stack Overflow用户
提问于 2011-01-02 20:14:11
回答 9查看 95.1K关注 0票数 63

我一直在使用JPA1.0( Hibernate驱动程序)中的Hibernate限制。有定义的Restrictions.ilike("column","keyword", MatchMode.ANYWHERE),它测试关键字是否匹配列在任何地方,它是不区分大小写的。

现在,我使用带有EclipseLink的JPA2.0作为驱动程序,所以我必须使用内置的“限制”JPA2.0。我找到了CriteriaBuilderlike方法,我还发现了如何使它在任何地方匹配(尽管它是令人敬畏和手动的),但我仍然没有弄清楚如何做到大小写不敏感。

这是我目前令人敬畏的解决办法:

代码语言:javascript
运行
复制
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<User> query = builder.createQuery(User.class);
EntityType<User> type = em.getMetamodel().entity(User.class);
Root<User> root = query.from(User.class);

// Where   
// important passage of code for question  
query.where(builder.or(builder.like(root.get(type.getDeclaredSingularAttribute("username", String.class)), "%" + keyword + "%"),
        builder.like(root.get(type.getDeclaredSingularAttribute("firstname", String.class)), "%" + keyword + "%"),
        builder.like(root.get(type.getDeclaredSingularAttribute("lastname", String.class)), "%" + keyword + "%")
        ));

// Order By
query.orderBy(builder.asc(root.get("lastname")),
            builder.asc(root.get("firstname")));

// Execute
return em.createQuery(query).
            setMaxResults(PAGE_SIZE + 1).
            setFirstResult((page - 1) * PAGE_SIZE).
            getResultList();

问题:

是否有类似于Hibernate驱动程序的功能?

我是否正确地使用了JPA2.0标准?与Hibernate限制相比,这是一种尴尬和不舒服的解决方案。

或者谁能帮我改变我的解决方案,使之不区分大小写,拜托?

非常感谢。

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2011-01-04 08:02:34

一开始它看起来有点尴尬,但它是类型安全的。从字符串构建查询不是这样,所以您在运行时而不是在编译时注意到错误。您可以通过使用缩进或单独执行每一步来提高查询的可读性,而不是在一行中写入整个WHERE子句。

要使查询不区分大小写,请将关键字和比较字段转换为小写:

代码语言:javascript
运行
复制
query.where(
    builder.or(
        builder.like(
            builder.lower(
                root.get(
                    type.getDeclaredSingularAttribute("username", String.class)
                )
            ), "%" + keyword.toLowerCase() + "%"
        ), 
        builder.like(
            builder.lower(
                root.get(
                    type.getDeclaredSingularAttribute("firstname", String.class)
                )
            ), "%" + keyword.toLowerCase() + "%"
        ), 
        builder.like(
            builder.lower(
                root.get(
                    type.getDeclaredSingularAttribute("lastname", String.class)
                )
            ), "%" + keyword.toLowerCase() + "%"
        )
    )
);
票数 114
EN

Stack Overflow用户

发布于 2017-11-24 16:58:36

正如我在(当前)接受的答案中所评论的那样,一方面使用DBMS的lower()函数,另一方面使用java的String.toLowerCase(),因为这两种方法都不适合为相同的输入字符串提供相同的输出。

我终于找到了一个更安全(但不是防弹的)解决方案,即让DBMS使用一个文字表达式执行所有的降低操作:

代码语言:javascript
运行
复制
builder.lower(builder.literal("%" + keyword + "%")

因此,完整的解决方案应该是:

代码语言:javascript
运行
复制
query.where(
    builder.or(
        builder.like(
            builder.lower(
                root.get(
                    type.getDeclaredSingularAttribute("username", String.class)
                )
            ), builder.lower(builder.literal("%" + keyword + "%")
        ), 
        builder.like(
            builder.lower(
                root.get(
                    type.getDeclaredSingularAttribute("firstname", String.class)
                )
            ), builder.lower(builder.literal("%" + keyword + "%")
        ), 
        builder.like(
            builder.lower(
                root.get(
                    type.getDeclaredSingularAttribute("lastname", String.class)
                )
            ), builder.lower(builder.literal("%" + keyword + "%")
        )
    )
);

编辑:

正如@cavpollo要求我举个例子一样,我不得不再三考虑我的解决方案,并意识到它并不比公认的答案安全得多:

代码语言:javascript
运行
复制
DB value* | keyword | accepted answer | my answer
------------------------------------------------
elie     | ELIE    | match           | match
Élie     | Élie    | no match        | match
Élie     | élie    | no match        | no match
élie     | Élie    | match           | no match

尽管如此,我还是更喜欢我的解决方案,因为它不会将结果与两种不同的功能进行比较,这两种功能应该是相同的。我将相同的函数应用于所有字符数组,以便比较输出更加“稳定”。

防弹解决方案将涉及区域设置,从而使SQL的lower()能够正确地降低重音字符。(但这超出了我所知的范围)

*Db值与带有'C‘语言环境的PostgreSQL 9.5.1

票数 14
EN

Stack Overflow用户

发布于 2014-05-07 13:22:03

这是我的工作:

代码语言:javascript
运行
复制
CriteriaBuilder critBuilder = em.getCriteriaBuilder();

CriteriaQuery<CtfLibrary> critQ = critBuilder.createQuery(Users.class);
Root<CtfLibrary> root = critQ.from(Users.class);

Expression<String> path = root.get("lastName");
Expression<String> upper =critBuilder.upper(path);
Predicate ctfPredicate = critBuilder.like(upper,"%stringToFind%");
critQ.where(critBuilder.and(ctfPredicate));
em.createQuery(critQ.select(root)).getResultList();
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4580285

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档