通过 Criteria api 在 LIKE 中转义字符
Escape character in LIKE through Criteria api
我试图让网络前端的用户在数据库中搜索某些属性。属性名称可能包括特殊的 SQL 字符 % 和 _,用于 like。有没有办法转义特殊字符?
我将 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 直达德比。这些表是从以下实体生成的。
SELECT * FROM ATTRIBUTESETMETA WHERE SETNAME LIKE 'Set%2'
returns 两行,如您所料(% = 通配符)。
我希望在标准中复制以下内容 API
SELECT * FROM ATTRIBUTESETMETA WHERE SETNAME LIKE 'Set\%2' ESCAPE '\'
这只是 returns 第一行,因为 \ 被明确设置为转义字符。
如果我用
SELECT * FROM ATTRIBUTEMETA WHERE SETNAME LIKE 'Set\%2'
没有转义条款,我什么也得不到(与其他数据库不同)
这是实体 class 和执行条件 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 查询和 returns 相同的结果。
有什么方法可以更改代码以使其表现得像我的第二个查询吗? (双关语)
在 JPA 中,CriteriaBuilder
的 like
方法有几个具有第三个参数的重载,即转义字符。它可以是 char
或 Expression<Character>
.
类型之一
因此,对于您的情况,最简单的方法是这样做:
cb.like(set.get(AttributeSetMeta_.setName), name, '\')
相关API 参考文献:
我试图让网络前端的用户在数据库中搜索某些属性。属性名称可能包括特殊的 SQL 字符 % 和 _,用于 like。有没有办法转义特殊字符?
我将 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 直达德比。这些表是从以下实体生成的。
SELECT * FROM ATTRIBUTESETMETA WHERE SETNAME LIKE 'Set%2'
returns 两行,如您所料(% = 通配符)。
我希望在标准中复制以下内容 API
SELECT * FROM ATTRIBUTESETMETA WHERE SETNAME LIKE 'Set\%2' ESCAPE '\'
这只是 returns 第一行,因为 \ 被明确设置为转义字符。
如果我用
SELECT * FROM ATTRIBUTEMETA WHERE SETNAME LIKE 'Set\%2'
没有转义条款,我什么也得不到(与其他数据库不同)
这是实体 class 和执行条件 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 查询和 returns 相同的结果。
有什么方法可以更改代码以使其表现得像我的第二个查询吗? (双关语)
在 JPA 中,CriteriaBuilder
的 like
方法有几个具有第三个参数的重载,即转义字符。它可以是 char
或 Expression<Character>
.
因此,对于您的情况,最简单的方法是这样做:
cb.like(set.get(AttributeSetMeta_.setName), name, '\')
相关API 参考文献: