comment utiliser regexp_like d’Oracle dans Hibernate HQL?

J’utilise oracle 10g et hibernate 3.3.2 . J’ai déjà utilisé l’expression régulière en SQL, maintenant que je l’utilise pour la première fois en HQL.

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

Ceci est mon hql, quand je le lance sans fonction regex_like , il fonctionne comme prévu. Mais je ne suis pas capable de l’exécuter avec regex_like expression regex_like .

Ça dit..

l’exception nestede est org.hibernate.hql.ast.QuerySyntaxException: noeud AST inattendu: (près de la ligne 1, colonne 66 …..

regex_like aider, comment puis-je utiliser regex_like dans une requête hibernate native? OU une autre alternative pour le faire.

En fait, vous ne pouvez pas comparer le résultat de REGEXP_LIKE à quoi que ce soit, sauf dans les instructions conditionnelles en PL / SQL.

Hibernate ne semble pas accepter une fonction personnalisée sans returnType, car vous devez toujours comparer le résultat à quelque chose, par exemple:

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

Comme Oracle ne vous permet pas de comparer le résultat de cette fonction à néant, j’ai proposé une solution utilisant la condition de casse:

 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)") ); } } 

Et votre HQL devrait ressembler à ceci:

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

Ça va marcher 🙂

Vous pouvez très certainement utiliser n’importe quel type de fonction spécifique à la firebase database que vous souhaitez avec Hibernate HQL (et JPQL, à condition que Hibernate en soit le fournisseur). Vous devez simplement parler à Hibernate de ces fonctions. En 3.3, la seule option possible consiste à fournir un dialecte personnalisé et à enregistrer la fonction à partir du constructeur du dialecte. Si vous examinez la classe de base Dialect, vous verrez de nombreux exemples d’enregistrement de fonctions. Il est généralement préférable d’étendre le dialecte exact que vous utilisez actuellement et de simplement fournir vos extensions (ici, enregistrez la fonction).

Une remarque intéressante est que Oracle ne classe pas regexp_like comme une fonction. Ils le classent comme condition / prédicat. Je pense que cela est principalement dû au fait qu’Oracle SQL ne définit pas un type de données BOOLEAN, même si leur PL / SQL le fait et je parierais que regexp_like est défini comme une fonction PL / SQL renvoyant BOOLEAN …

En supposant que vous utilisiez actuellement Oracle10gDialect, vous feriez:

 public class MyOracle10gDialect extends Oracle10gDialect { public Oracle10gDialect() { super(); registerFunction( "regexp_like", new StandardSQLFunction( "regexp_like", StandardBasicTypes.BOOLEAN ) ); } } 

Je ne me souviens pas si l’parsingur HQL aime les fonctions renvoyant des booléens, mais en tant que prédicat par lui-même. Vous devrez peut-être convertir true / false en quelque chose d’autre et vérifier par rapport à ce retour:

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

Vous pouvez essayer d’utiliser l’opérateur standard LIKE:

 where company.num like '%514619915' 

puis filtrer les indésirables à l’aide d’une expression rationnelle Java. Cela devrait réduire le nombre de lignes inutiles à renvoyer.

Cela n’utiliserait pas d’index car il commence par un ‘%’.

Vous ne pouvez accéder à des fonctions de firebase database spécifiques que si JPAQL / HQL fournit un moyen de le faire et ne fournit rien pour les expressions régulières. Vous devrez donc écrire une requête SQL native pour utiliser les expressions rationnelles.

Sur un autre point très important, quelques collègues (administrateurs de firebase database Oracle) m’ont dit de ne jamais utiliser de regex dans Oracle, car ils ne peuvent pas être indexés, ce qui aboutit à l’exécution par la firebase database d’une parsing complète. Si la table contient quelques entrées, tout va bien, mais si elle contient beaucoup de lignes, cela risque de paralyser les performances.

Pour ceux qui utilisent le critère Hibernate avec sqlRessortingction (Hibernate Version 4.2.7)

  Criterion someCriterion = Ressortingctions.sqlRessortingction("regexp_like (column_name, ?, 'i')", "(^|\\s)"+searchValue+"($|\\s|.$)", SsortingngType.INSTANCE); 

Une autre option consiste à créer une fonction similaire dans Oracle qui renverra une valeur numérique en fonction du résultat de l’opération. Quelque chose comme ca

 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; 

et vous pourrez utiliser

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