10

と を使用oracle 10gしてhibernate 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$' )");

これは私のhqlregex_likeです。関数なしで実行すると、期待どおりに実行されます。しかし、それをregex_like表現で実行することはできません。

それは言う..

ネストされた例外は org.hibernate.hql.ast.QuerySyntaxException: 予期しない AST ノード: ( 行 1、列 66 の近く.....

regex_like親切に助けてください、休止状態のネイティブクエリでどのように使用できますか? または、そうするための他の代替手段。

4

7 に答える 7

4

Hibernate HQL(およびHibernateがプロバイダーである限りJPQL)では、任意のタイプのデータベース固有の関数を確実に使用できます。これらの機能についてHibernateに伝える必要があります。3.3では、そのための唯一のオプションは、カスタムダイアレクトを提供し、ダイアレクトのコンストラクターから関数を登録することです。基本の方言クラスを見ると、関数の登録の例がたくさんあります。通常、現在使用している正確な方言を拡張し、拡張機能を提供するのが最善です(ここでは、関数を登録します)。

興味深いことに、Oracleはregexp_likeを関数として分類していません。彼らはそれを条件/述語として分類します。これは主に、Oracle SQLがBOOLEANデータ型を定義していないためだと思いますが、PL / SQLは定義しており、regexp_likeはBOOLEANを返すPL/SQL関数として定義されていると思います...

現在Oracle10gDialectを使用していると仮定すると、次のようになります。

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

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

HQLパーサーがブール値を返す関数を好むかどうかは思い出せませんが、それ自体が述語であるという点で。代わりに、true / falseを別のものに変換して、その戻り値をチェックする必要がある場合があります。

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 ) +
                             ")";
                 }
             }
        );
    }
}
于 2012-08-06T22:34:01.393 に答える
0

JPAQL/HQL がその方法を提供し、正規表現を提供しない限り、特定のデータベース機能にアクセスすることはできません。したがって、正規表現を使用するには、ネイティブ SQL クエリを作成する必要があります。

別の非常に重要な点として、何人かの同僚 (Oracle DBA) から、Oracle では正規表現を使用しないように言われました。これは、インデックスを作成できず、最終的に DB で完全な DB スキャンを実行することになるためです。テーブルにいくつかのエントリがある場合は問題ありませんが、行が多い場合はパフォーマンスが低下する可能性があります。

于 2012-08-03T09:55:21.827 に答える
0

標準の LIKE 演算子を使用してみてください。

where company.num like '%514619915'

次に、Java 正規表現を使用して不要なものを除外します。これにより、返される不要な行の数が減るはずです。

「%」で始まるため、これはインデックスを使用しません。

于 2012-08-06T13:27:27.517 に答える
0

sqlRestriction で Hibernate 基準を使用する場合 (Hibernate バージョン 4.2.7)

 Criterion someCriterion = Restrictions.sqlRestriction("regexp_like (column_name, ?, 'i')", "(^|\\s)"+searchValue+"($|\\s|.$)", StringType.INSTANCE);
于 2015-03-11T19:51:28.340 に答える
0

または、別のオプションは、操作結果に基づいて数値を返すオラクルで同様の関数を作成することです。そんな感じ

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
于 2015-09-25T12:12:47.850 に答える