在CriteriaBuilder中访问REGEXP_LIKE函数

问题描述 投票:1回答:1

我有一个多标准表单,正在使用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给出的说明。我已经按照说明注册了功能:

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的新手,因此感谢您可以给我的任何指针。谢谢

regex oracle criteria-api
1个回答
0
投票

[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> regExprLike = cb.function("regexp_instr", Integer.class, path, regExpr);
        Predicate localContact = cb.gt(regExprLike, 0);
        // Predicate localContact = cb.like(path, "%" + MISNumberUtils.toString(localContactPk) + "%");
        predicates.add(localContact);}

并且查询工作正常。

© www.soinside.com 2019 - 2024. All rights reserved.