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

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

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

问题

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

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

  1. @NamedQuery(
  2. name = DailyStatement.GET_EXPORT_DATES_BY_ORGASTRUCTUREIDS_FOR_MISEXPORT,
  3. query =
  4. " SELECT d.orgaStructureId, MIN(d.workingDay), MAX(d.workingDay) "
  5. + " FROM DailyStatement d "
  6. + " WHERE d.orgaStructureId in (:orgaStructureIds) "
  7. + " AND d.misExportFlag = false "
  8. + " AND d.state = net.shop.ob.ptm.types.timerecord.EDailyStatmentsState.CLOSED "
  9. + " AND d.workingDay <= :maxWorkingDay "
  10. + " 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 ]

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

  1. public enum EDailyStatmentsState {
  2. OPEN(0),
  3. ERROR(1),
  4. CLOSED(2);
  5. private int id;
  6. //(...)

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

  1. 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选项

  1. 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

  1. @NamedQuery(
  2. name = DailyStatement.GET_EXPORT_DATES_BY_ORGASTRUCTUREIDS_FOR_MISEXPORT,
  3. query =
  4. &quot; SELECT d.orgaStructureId, MIN(d.workingDay), MAX(d.workingDay) &quot;
  5. + &quot; FROM DailyStatement d &quot;
  6. + &quot; WHERE d.orgaStructureId in (:orgaStructureIds) &quot;
  7. + &quot; AND d.misExportFlag = false &quot;
  8. + &quot; AND d.state = net.shop.ob.ptm.types.timerecord.EDailyStatmentsState.CLOSED &quot;
  9. + &quot; AND d.workingDay &lt;= :maxWorkingDay &quot;
  10. + &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

  1. public enum EDailyStatmentsState {
  2. OPEN(0),
  3. ERROR(1),
  4. CLOSED(2);
  5. private int id;
  6. //(...)

The error does not occur if I set the hibernate parameter

  1. 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

  1. 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 中的以下正则表达式完成的:

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

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

  1. [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:

  1. [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

  1. [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:

确定