通过 Criteria api 在 LIKE 中转义字符

Posted

技术标签:

【中文标题】通过 Criteria api 在 LIKE 中转义字符【英文标题】:Escape character in LIKE through Criteria api 【发布时间】:2019-08-23 14:18:52 【问题描述】:

我正在尝试允许来自 Web 前端的用户在数据库中搜索某些属性。属性名称可能包括在 like 中使用的特殊 SQL 字符 % 和 _。有没有办法逃脱特殊字符?

我将 Criteria API 与 Glassfish 5.1、Apache Derby、JPA 2.1 和 EclipseLink 2.7.4 一起使用。

其他数据库使用 \ 作为默认转义字符,但 Derby 没有。从阅读来看,似乎严格的标准要求没有隐式转义字符。

我会用这些数据来说明:

ID           SETNAME             DESCRIPTION                                         
----------------------------------------------
1            Set_1               The very first set
2            Set%2               The second set

和 SQL 通过 JDBC 直接连接到 Derby。这些表是从以下实体生成的。

SELECT * FROM ATTRIBUTESETMETA WHERE SETNAME LIKE 'Set%2'

如您所料(% = 通配符)返回两行。

我希望在 Criteria API 中复制以下内容

SELECT * FROM ATTRIBUTESETMETA WHERE SETNAME LIKE 'Set\%2' ESCAPE '\'

它只返回第一行,因为 \ 被明确设置为转义字符。

如果我使用

SELECT * FROM ATTRIBUTEMETA WHERE SETNAME LIKE 'Set\%2'

没有转义子句,我什么也得不到(与其他数据库不同)

这里是执行条件 api 查询的实体类和包装器。

/* Imports ... */
@Entity
public class AttributeSetMeta implements Serializable 
    private static final long serialVersionUID = 3L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String setName;
    private String description;

// Getters and setters ...
// Imports
@Dependent
public class AttributeSetMetaFacade 

    @PersistenceContext(unitName = "oms")
    private EntityManager em;

    public AttributeSetMeatFacade() 
    

    public List<AttributeSetMeta> getSetByName(String name) 
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<AttributeSetMeta> cq = 
                cb.createQuery(AttributeSetMeta.class);
        Root<AttributeSetMeta> set = cq.from(AttributeSetMeta.class);
        cq.select(set)
                .where(cb.like(
                    set.get(AttributeSetMeta_.setName), name)
                );
        return em.createQuery(cq).getResultList();
    

// Other code ...

代码相当于我的第一个 SQL 查询并返回相同的结果。

有什么方法可以更改代码以使其表现得像我的第二个查询? (双关语)

【问题讨论】:

这只是this 方法,不是吗?我不太了解整个问题。 正是如此,谢谢。搜索时间太长而没有找到正确的地方:-( @M.Prokhorov 您能否将其添加为答案。谢谢 【参考方案1】:

在 JPA 中,CriteriaBuilderlike 方法有几个重载,其中有第三个参数,即转义字符。它可以是charExpression&lt;Character&gt; 类型之一。

因此,对于您的情况,最简单的方法是这样:

cb.like(set.get(AttributeSetMeta_.setName), name, '\\')

相关 API 参考:

like(Expression<String>, Expression<String>, char)

like(Expression<String>, String, char)

like(Expression<String>, Expression<String>, Expression<Character>)

like(Expression<String>, String, Expression<Character>)

【讨论】:

以上是关于通过 Criteria api 在 LIKE 中转义字符的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate Criteria API 中的 SQL 'LIKE' 运算符

Hibernate中 Restrictions.like() 方法

Mybatismybatis Example Criteria like 模糊查询

如何在 LIKE 子句中转义方括号?

在rails中转义SQL LIKE的查询

如何在 SQL Server Like 子句中转义通配符