如何使用Oracle在Hibernate的HQL REGEXP_LIKE?(how to use O

2019-06-26 18:20发布

我使用oracle 10ghibernate 3.3.2 。 我在SQL中使用正则表达式之前,现在对于我第一次使用它的HQL。

Query query = getSession().createQuery("From Company company 
where company.id!=:companyId and 
regexp_like(upper(rtrim(ltrim(company.num))), '^0*514619915$' )");

这是我的HQL,当我不运行它regex_like它运行正常功能。 但我不能够与执行它regex_like表达。

它说..

嵌套异常是org.hibernate.hql.ast.QuerySyntaxException:意想不到AST节点:(近线1,列66 .....

请帮帮忙,我该如何使用regex_like在休眠本地查询? 或其他一些替代这样做。

Answer 1:

其实,你可以不给REGEXP_LIKE的东西比较的结果除了在PL / SQL条件语句。

休眠似乎没有返回类型不接受自定义函数,因为你总是需要比较输出的东西,即:

REGEXP_LIKE('bananas', 'a', 'i') = 1

由于Oracle不允许你比较这函数的结果不了了之,我想出了使用条件的情况下的解决方案:

public class Oracle10gExtendedDialect extends Oracle10gDialect {

    public Oracle10gExtendedDialect() {
        super();
        registerFunction(
          "regexp_like", new SQLFunctionTemplate(StandardBasicTypes.BOOLEAN,
          "(case when (regexp_like(?1, ?2, ?3)) then 1 else 0 end)")
        );
    }

}

而你的HQL应该是这样的:

REGEXP_LIKE('bananas', 'a', 'i') = 1

它会工作:)



Answer 2:

您可以最肯定使用你(只要Hibernate是供应商和JPQL)希望与Hibernate的HQL任何类型的数据库特有的功能。 您只需告诉Hibernate那些功能。 在3.3的唯一选择是提供一个自定义的方言,并注册从方言的构造函数。 如果你看一看基方言类,你会看到很多的注册功能的示例。 平时最好延长您目前使用的确切的话,只需提供您的扩展(在这里,注册功能)。

一个有趣的注意的是,Oracle不归类为一个函数REGEXP_LIKE。 他们把它归类为条件/谓语。 我认为这主要是因为甲骨文的SQL不定义一个布尔数据类型,即使他们的PL / SQL不和我敢打赌REGEXP_LIKE被定义为PL / SQL函数返回布尔...

假设您目前使用Oracle10gDialect,你会怎么做:

public class MyOracle10gDialect extends Oracle10gDialect {
    public Oracle10gDialect() {
        super();

        registerFunction( 
            "regexp_like", 
             new StandardSQLFunction( "regexp_like", StandardBasicTypes.BOOLEAN )
        );
    }
}

我不记得,如果在HQL解析器喜欢在所有的本身是一个谓语方面然而返回布尔函数。 有时,您可能要真/假转换成别的东西并核对收益:

public class MyOracle10gDialect extends Oracle10gDialect {
    public Oracle10gDialect() {
        super();

        registerFunction( 
            "regexp_like", 
             new StandardSQLFunction( "regexp_like", StandardBasicTypes.INTEGER ) {
                 @Override
                 public String render(
                         Type firstArgumentType, 
                         List arguments, 
                         SessionFactoryImplementor factory) {
                     return "some_conversion_from_boolean_to_int(" + 
                             super.render( firstArgumentType, arguments, factory ) +
                             ")";
                 }
             }
        );
    }
}


Answer 3:

您可以尝试使用LIKE操作标准:

where company.num like '%514619915'

然后过滤掉使用Java正则表达式的不想要的。 这应该减少将返回不需要的行数。

因为它以“%”开始,这将不会使用索引。



Answer 4:

您不能访问特定的数据库功能,除非JPAQL / HQL提供一种方式来做到这一点,也不提供对正则表达式什么。 所以你需要写一个本地的SQL查询中使用正则表达式。

在另一个,而且很重要的一点,几个同事(的Oracle DBA)告诉我在甲骨文从来没有使用正则表达式,因为它们不能被索引,这在DB执行完整扫描DB结束了。 如果表中有几个条目,那么它的确定,但是如果它有大量的行,它可能会削弱性能。



Answer 5:

对于那些使用Hibernate则以sqlRestriction(休眠版本4.2.7)

 Criterion someCriterion = Restrictions.sqlRestriction("regexp_like (column_name, ?, 'i')", "(^|\\s)"+searchValue+"($|\\s|.$)", StringType.INSTANCE);


Answer 6:

或者另一种选择是在Oracle中创建类似的功能,这将返回基于运算结果的数值。 类似的东西

CREATE OR REPLACE FUNCTION MY_REGEXP_LIKE(text VARCHAR2, pattern VARCHAR2)
RETURN NUMBER 
IS function_result NUMBER;
BEGIN
  function_result := CASE WHEN REGEXP_LIKE(text, pattern) 
  THEN 1 
  ELSE 0
  END;    
  RETURN(function_result);
END MY_REGEXP_LIKE;

你将能够使用

MY_REGEXP_LIKE('bananas', 'a') = 1


文章来源: how to use Oracle's regexp_like in Hibernate HQL?