访问 CriteriaBuilder 中的 REGEXP_LIKE 函数

2024-03-17

我有一个多标准表单,并使用 CriteriaBuilder 来构建 sql。对于本地联系人条件,我需要使用 regexp_like 函数来搜索逗号分隔数字字符串中的数字字符串,即在字符串中搜索“234”,例如“1234,2345,6789,234”,它应该只返回完全匹配的记录,而不返回部分匹配的记录。

我已经在 Oracle 中测试了我的 regexp_like 语法,我使用的模式有效并给出了我期望的结果。

下面使用简单的java代码like有效(简化版本,仅考虑两个标准)

public List<ExpSessionInfoLightVO> findBySchedulingSearchExperimentsParams(String categoryCode, Integer categoryCounter,
        String expSessionPlaceHolderCategory, Date startsAfterDate, Date startsBeforeDate, Date endsAfterDate, Date endsBeforeDate,
        Long beamlinePk, Long pseudoBeamlinePk, Long runPk, Long scientistPk, String scientistRole, Long localContactPk,
        boolean showHiddenProposals, boolean withIHR) throws Exception {

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery cq = cb.createQuery();
    Root<ExpSessionInfoLightVO> esilvo = cq.from(ExpSessionInfoLightVO.class);

    // Constructing list of parameters
    List<Predicate> predicates = new ArrayList<>()

    // Local contact criteria
    if (localContactPk != null && localContactPk > 0) {
        Expression<String> path = esilvo.get("lcPks");
        Predicate localContact = cb.like(path, "%" + MISNumberUtils.toString(localContactPk) + "%");
        predicates.add(localContact);
    }

    // Run criteria
    if (runPk != null && runPk > 0) {
        Predicate beamline = cb.equal(esilvo.get("runNo"), runPk);
        predicates.add(beamline);
    }

    cq.select(esilvo).where(predicates.toArray(new Predicate[] {}));
    cq.orderBy(cb.asc(esilvo.get("startDate")));
    System.out.println(em.createQuery(cq).unwrap(org.hibernate.Query.class).getQueryString());
    // execute query
    return em.createQuery(cq).getResultList();

}

它生成以下查询:

select generatedAlias0 from ExpSessionInfoLightVO as generatedAlias0 where ( generatedAlias0.lcPks like :param0 ) and ( generatedAlias0.runNo=114L ) order by generatedAlias0.startDate asc

但是,如果我将本地联系人条件代码更改为:

if (localContactPk != null && localContactPk > 0) {
        Expression<String> regExpr = cb.literal("(^|\\s|\\w)(" + MISNumberUtils.toString(localContactPk) + ")($|\\s|\\w)");
        Expression<String> path = esilvo.get("lcPks");
        Expression<Boolean> regExprLike = cb.function("regexp_like", Boolean.class, path, regExpr);
        Predicate localContact = cb.equal(regExprLike, 1);
        predicates.add(localContact);
    }

我收到错误java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended.

尽管遵循给出的指示here https://stackoverflow.com/questions/11793159/how-to-use-oracles-regexp-like-in-hibernate-hql。我已经按照说明注册了该功能:

public class Oracle10gCustomDialect extends Oracle10gDialect { public Oracle10gCustomDialect() { super(); registerFunction("instr", new StandardSQLFunction("instr", IntegerType.INSTANCE)); registerFunction("regexp_like", new SQLFunctionTemplate(StandardBasicTypes.BOOLEAN, "(case when (regexp_like(?1, ?2)) then 1 else 0 end)")); } } 并且方言出现在 persistence.xml 文件中

      <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/> 

我是 java 和 JPA/Hibernate 方面的新手,因此非常感谢您能给我的任何指示。 谢谢


Oracle SQL 似乎不支持调用带有布尔参数或返回值的函数,而且 REGEXP_LIKE 是一个条件而不是函数。

为了解决这个问题,我使用了 REGEXP_INSTR,并像这样注册了它:

public class Oracle10gCustomDialect extends Oracle10gDialect {
public Oracle10gCustomDialect() {
    super();
    registerFunction("regexp_instr", new StandardSQLFunction("regexp_instr", IntegerType.INSTANCE));

并将我的代码更改为

        if (localContactPk != null && localContactPk > 0) {
        Expression<String> regExpr = cb.literal("(^|\\s|\\w)(" + MISNumberUtils.toString(localContactPk) + ")($|\\s|\\w)");
        Expression<String> path = esilvo.get("lcPks");
        Expression<Integer> regExprInstr = cb.function("regexp_instr", Integer.class, path, regExpr);
        Predicate localContact = cb.gt(regExprInstr, 0);

        predicates.add(localContact);}

并且查询工作正常。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

访问 CriteriaBuilder 中的 REGEXP_LIKE 函数 的相关文章

随机推荐