休眠条件查询以使用MySQL REPLACE和CONCAT函数

时间:2019-04-23 07:41:00

标签: mysql hibernate jpa hibernate-criteria

尝试使用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"))

1 个答案:

答案 0 :(得分:1)

Concat可通过构建器使用,因此您真正需要添加的只是replace函数。

您需要做的是创建一个实现org.hibernate.boot.spi.MetadataBuilderInitializer的类,并使用该类向Hibernate注册功能。假设您的班级叫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加载它。如果这样的目录不存在,请创建它。该文件必须包含实现类的全名,并以新行结尾。

最后使用它:

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驱动程序在该位置安全地发送字符串。

但是,如果要删除所有空白而不是仅删除所有0x20空格字符,则应将\s+之类的正则表达式与我放在MetaContrib中的其他函数一起使用。仅当您的MySQL为8.0.4或更高版本,或MariaDB 10.0.8或更高版本时,才可以这样做。该函数存在于MariaDB10Dialect中,因此,如果您使用的是MariaDB,则可能不需要MetaContrib类。