Hibernate QuerySyntaxException with enum when hibernate.query.conventional_java_constants is set to false

huangapple go评论77阅读模式
英文:

Hibernate QuerySyntaxException with enum when hibernate.query.conventional_java_constants is set to false

问题

背景:使用Java 8和Hibernate 5.3.9.Final的Java/Wildfly/Hibernate应用程序。

我有一个类似这样的命名查询:

  @NamedQuery(
    name = DailyStatement.GET_EXPORT_DATES_BY_ORGASTRUCTUREIDS_FOR_MISEXPORT,
    query =
            " SELECT d.orgaStructureId, MIN(d.workingDay), MAX(d.workingDay) "
                    + "   FROM DailyStatement d "
                    + "  WHERE d.orgaStructureId in (:orgaStructureIds) "
                    + "    AND d.misExportFlag = false "
                    + "    AND d.state = net.shop.ob.ptm.types.timerecord.EDailyStatmentsState.CLOSED "
                    + "    AND d.workingDay <= :maxWorkingDay "
                    + " GROUP BY d.orgaStructureId "

在启动应用程序时,我收到一个错误:

DailyStatement.getExportDatesByOrgaStructureIdsForMISExport失败
原因是:org.hibernate.hql.internal.ast.QuerySyntaxException:
无效路径:
'net.shop.ob.ptm.types.timerecord.EDailyStatmentsState.CLOSED' [
SELECT d.orgaStructureId, MIN(d.workingDay), MAX(d.workingDay) FROM
net.shop.ob.ptm.dm.entities.DailyStatement d WHERE d.orgaStructureId
in (:orgaStructureIds) AND d.misExportFlag = false AND d.state
= net.shop.ob.ptm.types.timerecord.EDailyStatmentsState.CLOSED AND d.workingDay <= :maxWorkingDay GROUP BY d.orgaStructureId ]

所谓的错误枚举看起来像这样:

public enum EDailyStatmentsState {
    OPEN(0),
    ERROR(1),
    CLOSED(2);

    private int id;

    //(...)

如果我将persistence.xml中的Hibernate参数

hibernate.query.conventional_java_constants

设置为false,错误就不会发生。在博文https://vladmihalcea.com/the-performance-penalty-of-class-forname-when-parsing-jpql-and-criteria-queries/中解释了此参数的含义。如果常量EDailyStatmentsState.CLOSED不遵循标准的Java命名约定,我会理解这个错误,但据我所见,它确实遵循命名约定。

出于性能原因,我想将Hibernate选项

hibernate.query.conventional_java_constants

设置为false并修复错误的根本原因。可能是什么原因导致这个问题?

顺便说一下,这个问题与诸如这个问题https://stackoverflow.com/questions/59543649/querysyntaxexception-with-enum不重复,
因为在那里,非标准的小写枚举命名导致了错误,而在我的情况下则不是这样。

英文:

Background: Java/Wildfly/Hibernate application with Java 8 and Hibernate 5.3.9.Final.

I have a named query like this

  @NamedQuery(
    name = DailyStatement.GET_EXPORT_DATES_BY_ORGASTRUCTUREIDS_FOR_MISEXPORT,
    query =
            &quot; SELECT d.orgaStructureId, MIN(d.workingDay), MAX(d.workingDay) &quot;
                    + &quot;   FROM DailyStatement d &quot;
                    + &quot;  WHERE d.orgaStructureId in (:orgaStructureIds) &quot;
                    + &quot;    AND d.misExportFlag = false &quot;
                    + &quot;    AND d.state = net.shop.ob.ptm.types.timerecord.EDailyStatmentsState.CLOSED &quot;
                    + &quot;    AND d.workingDay &lt;= :maxWorkingDay &quot;
                    + &quot; GROUP BY d.orgaStructureId &quot;

When starting the application I get an error

> DailyStatement.getExportDatesByOrgaStructureIdsForMISExport failed
> because of: org.hibernate.hql.internal.ast.QuerySyntaxException:
> Invalid path:
> 'net.shop.ob.ptm.types.timerecord.EDailyStatmentsState.CLOSED' [
> SELECT d.orgaStructureId, MIN(d.workingDay), MAX(d.workingDay) FROM
> net.shop.ob.ptm.dm.entities.DailyStatement d WHERE d.orgaStructureId
> in (:orgaStructureIds) AND d.misExportFlag = false AND d.state
> = net.shop.ob.ptm.types.timerecord.EDailyStatmentsState.CLOSED AND d.workingDay <= :maxWorkingDay GROUP BY d.orgaStructureId ]

The referenced, allegedly erroneous enum looks like this

public enum EDailyStatmentsState {
    OPEN(0),
    ERROR(1),
    CLOSED(2);

    private int id;

    //(...)

The error does not occur if I set the hibernate parameter

hibernate.query.conventional_java_constants

to false

in persistence.xml. In blog post https://vladmihalcea.com/the-performance-penalty-of-class-forname-when-parsing-jpql-and-criteria-queries/ the meaning of this parameter is explained. I would understand the error, if the constant EDailyStatmentsState.CLOSED would not follow standard Java naming conventions, but as far as I can see, it does.

Because of performance reasons I would like to set the Hibernate option

hibernate.query.conventional_java_constants

to false and fix the root cause of the error. What could be causing this?

BTW, This question is not a duplicate of e.g. this question https://stackoverflow.com/questions/59543649/querysyntaxexception-with-enum
as the non-standard lower-case enum naming is causing the error there, unlike in my case.

答案1

得分: 1

显然问题在于 Hibernate 中对类名的验证是通过类 org.hibernate.internal.util.ReflectHelper 中的以下正则表达式完成的:

[a-z\d]+\.([A-Z]{1}[a-z\d]+)+$?([A-Z]{1}[a-z\d]+)*\.[A-Z_$]+

这会导致具有两个连续大写字母的类无法通过验证。这是一个已知的 Hibernate 错误 (HHH-14059),已通过在 Hibernate 中进行了内部修复,将有问题的正则表达式替换为:

[a-z\d]+\.([A-Z]+[a-z\d]+)+$?([A-Z]{1}[a-z\d]+)*\.[A-Z_$]+

我通过将类名重命名为不包含连续大写字母的方式解决了这个问题。

这个问题在 Hibernate 5.4.19 中也已经被修复。

英文:

Apparently the problem is that the validation of the classname in Hibrnate is done with the following regex in class org.hibernate.internal.util.ReflectHelper:

[a-z\d]+\.([A-Z]{1}[a-z\d]+)+$?([A-Z]{1}[a-z\d]+)*\.[A-Z_$]+

This causes classes with two successive uppercase letters not to validate. This is a known Hibernate bug (HHH-14059) which has been internally fixed in Hibernate by replacing the offending regex with

[a-z\d]+\.([A-Z]+[a-z\d]+)+$?([A-Z]{1}[a-z\d]+)*\.[A-Z_$]+

I fixed the issue with a workaround by renaming the class to contain no consecutive uppercase letters.

The issue has also been fixed in Hibernate 5.4.19.

huangapple
  • 本文由 发表于 2020年10月20日 22:25:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/64447242.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定