HQL不允许使用Hibernate 5对MySQL进行REGEXP或RLIKE

时间:2017-12-20 00:14:29

标签: java mysql spring-data-jpa hql hibernate-5.x

我尝试将 RLIKE 条件添加到 HQL 查询中,但我得到了&#34; 意外令牌:rlike < /强>&#34; HQL验证时出现错误消息。

我使用Spring引导Spring-data和Hibernate 5而不是MySQL。

查询:

@Query("from PortEntity p where  p.name rlike '(gigabit)-(\\d)\\/(\\d)' ")
@EntityGraph(attributePaths = {"parentSlot", "parentSlot.device"})
List<PortEntity> findGigabitDevices(Pageable pageable);

错误日志:

01:26:21.033 16751 [restartedMain] DEBUG o.h.hql.internal.ast.ErrorCounter incident: - throwQueryException() : no errors 
01:26:21.035 16753 [restartedMain] DEBUG o.h.h.i.ast.QueryTranslatorImpl incident: - parse() - HQL: from com.***.***.entity.PortEntity p where p.name rlike '(gigabit)-(\d)\/(\d)'  
01:26:21.037 16755 [restartedMain] ERROR o.h.hql.internal.ast.ErrorCounter incident: - line 1:75: unexpected token: rlike 
01:26:21.043 16761 [restartedMain] ERROR o.h.hql.internal.ast.ErrorCounter incident: - line 1:75: unexpected token: rlike 
antlr.NoViableAltException: unexpected token: rlike
        at org.hibernate.hql.internal.antlr.HqlBaseParser.queryRule(HqlBaseParser.java:784)
        at org.hibernate.hql.internal.antlr.HqlBaseParser.selectStatement(HqlBaseParser.java:316)
        at org.hibernate.hql.internal.antlr.HqlBaseParser.statement(HqlBaseParser.java:198)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:283)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:186)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:141)
        at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115)
        at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
        at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
        at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:546)
        at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:655)
        at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:23)
        at sun.reflect.GeneratedMethodAccessor64.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:347)
        at com.sun.proxy.$Proxy152.createQuery(Unknown Source)
        at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:86)
        at org.springframework.data.jpa.repository.query.SimpleJpaQuery.<init>(SimpleJpaQuery.java:62)
        at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromMethodWithQueryString(JpaQueryFactory.java:72)
        at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromQueryAnnotation(JpaQueryFactory.java:53)
        at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$DeclaredQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:144)
        at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:212)
        at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:77)

我发现在新的Hibernate版本中,HQL是通过基于ANTLR的解析器解析的,而它的语法只是没有 REGEX RLIKE 关键字: Hibernate HQL ANTLR grammar

我尝试通过添加Hibernate属性

切换到经典的HQL解析器
"hibernate.query.factory_class" = "org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory"

但是在这种情况下@EntityGraph停止使用消息&#34;使用经典QueryTranslator &#34;

无法应用EntityGraphs查询
01:56:59.412 91498 [http-nio-8080-exec-1] WARN  o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver incident:REQID3302215661531 - Resolved exception caused by Handler execution: org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.QueryException: EntityGraphs cannot be applied queries using the classic QueryTranslator!; nested exception is java.lang.IllegalArgumentException: org.hibernate.QueryException: EntityGraphs cannot be applied queries using the classic QueryTranslator!

是否应该配置某些内容以允许在基于ANTLR的解析器的Hibernate 5中使用RLIKE / REGEXP,或者它的错误?

2 个答案:

答案 0 :(得分:0)

基本上,要在Hibernate中使用MySQL rlike函数,我们需要创建一个&#34; SQLFunctionTemplate&#34;。

现在,该怎么做:

首先:创建一个名为&#34; AppMySQLDialect&#34;的类。并从MySQLDialect扩展然后覆盖空构造函数,最后注册regexp函数:

public class AppMySQLDialect extends MySQLDialect {
    public AppMySQLDialect() {
        super();
        /**
         * Function to evaluate regexp in MySQL
         */
        registerFunction("rlike", new SQLFunctionTemplate(Hibernate.INTEGER, "?1 rlike ?2"));
    }
}

好的,现在让我们按照以下方式使用它:

FROM PortEntity p where rlike(p.name, '(gigabit)-(\\d)\\/(\\d)') = 1

创建您的HibernateQuery并执行。

对于Hibernate 5,您可以查看: https://stackoverflow.com/a/41369853/1715121

答案 1 :(得分:0)

似乎不可能。 Hibernate 5不适用于HQL,但适用于具有标准的JPQL。 这个标准(由ANTLR解析器实现)只是没有声明REGEXP / RLIKE支持。

JPQL Language Reference