英文:
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 =
" 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 "
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论