Hibernate Criteria Query 使用 MySQL REPLACE 和 CONCAT 函数
Hibernate Criteria Query to use MySQL REPLACE and CONCAT functions
尝试使用 CriteriaBuilder
在 Hibernate 中复制以下 MySQL 查询。此查询添加名字和姓氏,删除中间的所有空格并搜索与给定字符串匹配的结果。
select * from users where replace(concat(first_name, last_name), " ", "") like 'jamesbon%';
final CriteriaBuilder criteriaBuilder = getCurrentSession().getCriteriaBuilder();
final CriteriaQuery<UserImpl> userCriteriaQuery = criteriaBuilder.createQuery(UserImpl.class);
final Root<UserImpl> userRoot = userCriteriaQuery.from(UserImpl.class);
// criteriaBuilder.concat(userRoot .get("firstName"), userRoot .get("lastName"))
Concat 可通过构建器获得,因此您真正需要添加的只是 replace
函数。
您需要做的是创建一个实现 org.hibernate.boot.spi.MetadataBuilderInitializer
的 class 并使用它向 Hibernate 注册函数。假设您的 class 被称为 com.project.hibernate.MetaContrib
package com.project.hibernate;
import org.hibernate.boot.MetadataBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.spi.MetadataBuilderInitializer;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.type.StringType;
public class MetaContrib implements MetadataBuilderInitializer {
@Override
public void contribute(MetadataBuilder metadataBuilder, StandardServiceRegistry serviceRegistry) {
metadataBuilder.applySqlFunction("str_replace", new StandardSQLFunction("replace", StringType.INSTANCE));
metadataBuilder.applySqlFunction("regex_replace", new StandardSQLFunction("REGEXP_REPLACE", StringType.INSTANCE));
}
}
下一步是通过在资源的 META-INF/services
目录中创建一个名为 org.hibernate.boot.spi.MetadataBuilderInitializer
的文件来告诉 Hibernate 加载它。如果这样的目录不存在,请创建它。该文件必须包含实施的全名 class,并以新行结尾。
终于可以使用了:
expr1 = criteriaBuilder.concat(userRoot.get("firstName"), userRoot.get("lastName"));
expr2 = criteriaBuilder.function("str_replace", String.class, expr1, " ", "");
expr3 = criteriaBuilder.like(expr2, cb.parameter(String.class, "sv"));
userCriteriaQuery.where(expr3)
return createQuery(userCriteriaQuery)
.setParameter("sv", "jamesbon%")
.getResultList();
详细解释:
CriteriaBuilder 创建 JPQL 查询。你的函数表达式变成这样:
... WHERE function('str_replace', concat(u.firstName, u.lastName), ' ', '') LIKE :sv
呈现给本机查询时将如下所示:
where replace(concat(u0.first_name, u0.last_name), ' ', '') like :sv
该函数在 JPQL 中以名称 str_replace
注册,但它可以是您选择的任何名称。这是您为 StandardSQLFunction
构造函数指定的名称,告诉它本机名称是什么。
然后 :sv
在内部变成 ?
,当您使用 setParameter 时,它告诉 JDBC 驱动程序在那个位置安全地发送字符串。
但是,如果你想删除所有的白色space,而不是仅仅删除所有 0x20 space 个字符,你应该使用像 \s+
这样的正则表达式和我输入的另一个函数MetaContrib
。只有当您的 MySQL 是 8.0.4 或更高版本,或者 MariaDB 10.0.8 或更高版本时,您才能这样做。该函数存在于 MariaDB10Dialect 中,因此如果您使用的是 MariaDB,则可能不需要 MetaContrib
class.
尝试使用 CriteriaBuilder
在 Hibernate 中复制以下 MySQL 查询。此查询添加名字和姓氏,删除中间的所有空格并搜索与给定字符串匹配的结果。
select * from users where replace(concat(first_name, last_name), " ", "") like 'jamesbon%';
final CriteriaBuilder criteriaBuilder = getCurrentSession().getCriteriaBuilder();
final CriteriaQuery<UserImpl> userCriteriaQuery = criteriaBuilder.createQuery(UserImpl.class);
final Root<UserImpl> userRoot = userCriteriaQuery.from(UserImpl.class);
// criteriaBuilder.concat(userRoot .get("firstName"), userRoot .get("lastName"))
Concat 可通过构建器获得,因此您真正需要添加的只是 replace
函数。
您需要做的是创建一个实现 org.hibernate.boot.spi.MetadataBuilderInitializer
的 class 并使用它向 Hibernate 注册函数。假设您的 class 被称为 com.project.hibernate.MetaContrib
package com.project.hibernate;
import org.hibernate.boot.MetadataBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.spi.MetadataBuilderInitializer;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.type.StringType;
public class MetaContrib implements MetadataBuilderInitializer {
@Override
public void contribute(MetadataBuilder metadataBuilder, StandardServiceRegistry serviceRegistry) {
metadataBuilder.applySqlFunction("str_replace", new StandardSQLFunction("replace", StringType.INSTANCE));
metadataBuilder.applySqlFunction("regex_replace", new StandardSQLFunction("REGEXP_REPLACE", StringType.INSTANCE));
}
}
下一步是通过在资源的 META-INF/services
目录中创建一个名为 org.hibernate.boot.spi.MetadataBuilderInitializer
的文件来告诉 Hibernate 加载它。如果这样的目录不存在,请创建它。该文件必须包含实施的全名 class,并以新行结尾。
终于可以使用了:
expr1 = criteriaBuilder.concat(userRoot.get("firstName"), userRoot.get("lastName"));
expr2 = criteriaBuilder.function("str_replace", String.class, expr1, " ", "");
expr3 = criteriaBuilder.like(expr2, cb.parameter(String.class, "sv"));
userCriteriaQuery.where(expr3)
return createQuery(userCriteriaQuery)
.setParameter("sv", "jamesbon%")
.getResultList();
详细解释:
CriteriaBuilder 创建 JPQL 查询。你的函数表达式变成这样:
... WHERE function('str_replace', concat(u.firstName, u.lastName), ' ', '') LIKE :sv
呈现给本机查询时将如下所示:
where replace(concat(u0.first_name, u0.last_name), ' ', '') like :sv
该函数在 JPQL 中以名称 str_replace
注册,但它可以是您选择的任何名称。这是您为 StandardSQLFunction
构造函数指定的名称,告诉它本机名称是什么。
然后 :sv
在内部变成 ?
,当您使用 setParameter 时,它告诉 JDBC 驱动程序在那个位置安全地发送字符串。
但是,如果你想删除所有的白色space,而不是仅仅删除所有 0x20 space 个字符,你应该使用像 \s+
这样的正则表达式和我输入的另一个函数MetaContrib
。只有当您的 MySQL 是 8.0.4 或更高版本,或者 MariaDB 10.0.8 或更高版本时,您才能这样做。该函数存在于 MariaDB10Dialect 中,因此如果您使用的是 MariaDB,则可能不需要 MetaContrib
class.