Null Pointer Exception when using Hibernate 5.4 and Enumerations in Named Query

I am upgrading from Hibernate 5.1 to Hibernate 5.4, and I am using some enumeration values in a named query.

In 5.1, I needed to provide the fully qualified enum (class)name, however in 5.4 that results in an error building the entity manager: Invalid path. (Full log below)
I found out (by trial and error) that I do not need to provide anything except the value now, and that seems to be working properly.

However, in my adventure, I found that if you give the classname of the enumeration, it will cause a NPE.
Although I am past this now, I thought I should probably report it anyway.

I rewrote it into the smallest example.

5.1 Code:

package com.jamie.test;

import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;

@Entity
@NamedQueries(value= {
		@NamedQuery(name="UserEntity.findRemoteAuthUsers", 
			query="SELECT row FROM UserEntity row WHERE auth IN (com.jamie.test.UserEntity.AUTH.LDAP, com.jamie.test.UserEntity.AUTH.OAuth)")
})
public class UserEntity
{
	@Id
	public Long id;
	
	enum AUTH {LDAP, OAuth, NONE}
	
	@Enumerated(EnumType.ORDINAL)
	public AUTH auth;
}

Under Hibernate 5.1, this works as expected.

Using Hibernate 5.4, it results in the following exception:

Feb 09, 2021 5:04:10 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
Feb 09, 2021 5:04:11 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@68d651f2] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Feb 09, 2021 5:04:11 PM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Feb 09, 2021 5:04:11 PM org.hibernate.hql.internal.ast.ErrorTracker reportError
ERROR:  Invalid path: 'com.jamie.test.UserEntity.AUTH.LDAP'
Feb 09, 2021 5:04:11 PM org.hibernate.hql.internal.ast.ErrorTracker reportError
ERROR:  Invalid path: 'com.jamie.test.UserEntity.AUTH.LDAP'
 Invalid path: 'com.jamie.test.UserEntity.AUTH.LDAP'
	at org.hibernate.hql.internal.ast.util.LiteralProcessor.lookupConstant(LiteralProcessor.java:111)
	at org.hibernate.hql.internal.ast.tree.DotNode.resolve(DotNode.java:219)
	at org.hibernate.hql.internal.ast.HqlSqlWalker.resolve(HqlSqlWalker.java:1053)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.expr(HqlSqlBaseWalker.java:1308)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.inRhs(HqlSqlBaseWalker.java:4947)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.comparisonExpr(HqlSqlBaseWalker.java:4561)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2166)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.whereClause(HqlSqlBaseWalker.java:832)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:626)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:330)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:278)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:276)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:192)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73)
	at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162)
	at org.hibernate.query.spi.NamedQueryRepository.checkNamedQueries(NamedQueryRepository.java:159)
	at org.hibernate.internal.SessionFactoryImpl.checkNamedQueries(SessionFactoryImpl.java:570)
	at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:329)
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:468)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1259)
	at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:56)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
	at com.jamie.test.Main.main(Main.java:11)

Feb 09, 2021 5:04:11 PM org.hibernate.internal.SessionFactoryImpl <init>
ERROR: HHH000177: Error in named query: UserEntity.findRemoteAuthUsers
org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'com.jamie.test.UserEntity.AUTH.LDAP' [SELECT row FROM com.jamie.test.UserEntity row WHERE auth IN (com.jamie.test.UserEntity.AUTH.LDAP, com.jamie.test.UserEntity.AUTH.OAuth)]
	at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74)
	at org.hibernate.hql.internal.ast.ErrorTracker.throwQueryException(ErrorTracker.java:93)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:282)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:192)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73)
	at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162)
	at org.hibernate.query.spi.NamedQueryRepository.checkNamedQueries(NamedQueryRepository.java:159)
	at org.hibernate.internal.SessionFactoryImpl.checkNamedQueries(SessionFactoryImpl.java:570)
	at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:329)
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:468)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1259)
	at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:56)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
	at com.jamie.test.Main.main(Main.java:11)

Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit: jamtest] Unable to build Hibernate SessionFactory
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:1336)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1262)
	at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:56)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
	at com.jamie.test.Main.main(Main.java:11)
Caused by: org.hibernate.HibernateException: Errors in named queries: 
UserEntity.findRemoteAuthUsers failed because of: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'com.jamie.test.UserEntity.AUTH.LDAP' [SELECT row FROM com.jamie.test.UserEntity row WHERE auth IN (com.jamie.test.UserEntity.AUTH.LDAP, com.jamie.test.UserEntity.AUTH.OAuth)]
	at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:343)
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:468)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1259)
	... 4 more

And so, changing the source to remove the everything but the enum values, like the following, works in 5.4

    query="SELECT row FROM UserEntity row WHERE auth IN (LDAP, OAuth)")

However, just for the sake of completeness, the following variations caused an NPE:

    query="SELECT row FROM UserEntity row WHERE auth IN (UserEntity.AUTH.LDAP, UserEntity.AUTH.OAuth)")
or
    query="SELECT row FROM UserEntity row WHERE auth IN (AUTH.LDAP, AUTH.OAuth)")

And, the resulting exception:

Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit: ccs] Unable to build Hibernate SessionFactory
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:1336)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1262)
	at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:56)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
	at com.counterpath.ccscommon.server.EntityManagerSingleton.getEntityManager(EntityManagerSingleton.java:241)
	at com.counterpath.ccscommon.server.EntityManagerSingleton.getEntityManager(EntityManagerSingleton.java:142)
	at com.counterpath.ccscommon.server.Testy.main(Testy.java:12)
Caused by: java.lang.NullPointerException
	at java.base/java.lang.String$CaseInsensitiveComparator.compare(String.java:1224)
	at java.base/java.lang.String$CaseInsensitiveComparator.compare(String.java:1218)
	at java.base/java.util.TreeMap.getEntryUsingComparator(TreeMap.java:374)
	at java.base/java.util.TreeMap.getEntry(TreeMap.java:343)
	at java.base/java.util.TreeMap.get(TreeMap.java:277)
	at org.hibernate.dialect.function.SQLFunctionRegistry.findSQLFunction(SQLFunctionRegistry.java:45)
	at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.findSQLFunction(SessionFactoryHelper.java:385)
	at org.hibernate.hql.internal.ast.tree.IdentNode.getDataType(IdentNode.java:367)
	at org.hibernate.hql.internal.ast.HqlSqlWalker.lookupProperty(HqlSqlWalker.java:667)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.addrExpr(HqlSqlBaseWalker.java:5075)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.addrExprLhs(HqlSqlBaseWalker.java:5783)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.addrExpr(HqlSqlBaseWalker.java:5060)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.expr(HqlSqlBaseWalker.java:1304)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.inRhs(HqlSqlBaseWalker.java:4947)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.comparisonExpr(HqlSqlBaseWalker.java:4561)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2166)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2094)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2091)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.whereClause(HqlSqlBaseWalker.java:832)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:626)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:330)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:278)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:276)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:192)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73)
	at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162)
	at org.hibernate.query.spi.NamedQueryRepository.checkNamedQueries(NamedQueryRepository.java:159)
	at org.hibernate.internal.SessionFactoryImpl.checkNamedQueries(SessionFactoryImpl.java:570)
	at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:329)
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:468)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1259)
	... 5 more

Anyway, just thought I’d mention it!

Inner classes are separated by $ in Java, so I think the following should work SELECT row FROM UserEntity row WHERE auth IN (com.jamie.test.UserEntity$AUTH.LDAP, com.jamie.test.UserEntity$AUTH.OAuth)

Hello, thanks for the response!

This seems to be worse than I thought.
I have been trying all sorts of combinations of things, and I am unable to use any form of an enumeration value in a named query and have it work properly.
I have discovered that my suggested solution does not actually work when you try to run the query.

Most cases resulted in an ‘invalid path’ error.
Some cases resulted in a NPE
Some cases resulted in an error while using the query, ‘Column ldap does not exist’

What I tried:

  1. Unadorned values:
    query=“SELECT row FROM UserEntity row WHERE auth IN (LDAP, OAuth)”
    This compiles okay, and I get an entity manager, however when I run the query, I get the following error:
Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not extract ResultSet
	at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:103)
	at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99)
	at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:67)
	at org.hibernate.loader.Loader.getResultSet(Loader.java:2303)
	at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2056)
	at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2018)
	at org.hibernate.loader.Loader.scroll(Loader.java:2926)
	at org.hibernate.loader.hql.QueryLoader.scroll(QueryLoader.java:576)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.scroll(QueryTranslatorImpl.java:452)
	at org.hibernate.engine.query.spi.HQLQueryPlan.performScroll(HQLQueryPlan.java:353)
	at org.hibernate.internal.SessionImpl.scroll(SessionImpl.java:1556)
	at org.hibernate.query.internal.AbstractProducedQuery.doScroll(AbstractProducedQuery.java:1562)
	at org.hibernate.query.internal.AbstractProducedQuery.scroll(AbstractProducedQuery.java:1548)
	at org.hibernate.query.internal.AbstractProducedQuery.stream(AbstractProducedQuery.java:1572)
	at org.hibernate.query.Query.getResultStream(Query.java:1140)
	at com.jamie.test.Main.main(Main.java:40)
Caused by: org.postgresql.util.PSQLException: ERROR: column "ldap" does not exist
etc...
  1. Added enum classname
    query=“SELECT row FROM UserEntity row WHERE auth IN (AUTH.LDAP, AUTH.OAuth)”)
ERROR:  Invalid path: 'AUTH.LDAP'
 Invalid path: 'AUTH.LDAP'
	at org.hibernate.hql.internal.ast.util.LiteralProcessor.lookupConstant(LiteralProcessor.java:111)
	at org.hibernate.hql.internal.ast.tree.DotNode.resolve(DotNode.java:219)
	at org.hibernate.hql.internal.ast.HqlSqlWalker.resolve(HqlSqlWalker.java:1053)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.expr(HqlSqlBaseWalker.java:1308)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.inRhs(HqlSqlBaseWalker.java:4947)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.comparisonExpr(HqlSqlBaseWalker.java:4561)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2166)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.whereClause(HqlSqlBaseWalker.java:832)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:626)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:330)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:278)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:276)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:192)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73)
	at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162)
	at org.hibernate.query.spi.NamedQueryRepository.checkNamedQueries(NamedQueryRepository.java:159)
	at org.hibernate.internal.SessionFactoryImpl.checkNamedQueries(SessionFactoryImpl.java:570)
	at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:329)
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:468)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1259)
	at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:56)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
	at com.jamie.test.Main.main(Main.java:17)

Feb 12, 2021 4:15:46 PM org.hibernate.internal.SessionFactoryImpl <init>
ERROR: HHH000177: Error in named query: UserEntity.findRemoteAuthUsers
org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'AUTH.LDAP' [SELECT row FROM com.jamie.test.UserEntity row WHERE auth IN (AUTH.LDAP, AUTH.OAuth)]
	at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74)
	at org.hibernate.hql.internal.ast.ErrorTracker.throwQueryException(ErrorTracker.java:93)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:282)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:192)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73)
	at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162)
	at org.hibernate.query.spi.NamedQueryRepository.checkNamedQueries(NamedQueryRepository.java:159)
	at org.hibernate.internal.SessionFactoryImpl.checkNamedQueries(SessionFactoryImpl.java:570)
	at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:329)
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:468)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1259)
	at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:56)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
	at com.jamie.test.Main.main(Main.java:17)

Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit: jamtest] Unable to build Hibernate SessionFactory
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:1336)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1262)
	at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:56)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
	at com.jamie.test.Main.main(Main.java:17)
Caused by: org.hibernate.HibernateException: Errors in named queries: 
UserEntity.findRemoteAuthUsers failed because of: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'AUTH.LDAP' [SELECT row FROM com.jamie.test.UserEntity row WHERE auth IN (AUTH.LDAP, AUTH.OAuth)]
	at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:343)
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:468)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1259)
  1. Added outer classname
    query=“SELECT row FROM UserEntity row WHERE auth IN (UserEntity.AUTH.LDAP, UserEntity.AUTH.OAuth)”)
Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit: jamtest] Unable to build Hibernate SessionFactory
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:1336)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1262)
	at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:56)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
	at com.jamie.test.Main.main(Main.java:17)
Caused by: java.lang.NullPointerException
	at java.base/java.lang.String$CaseInsensitiveComparator.compare(String.java:1224)
	at java.base/java.lang.String$CaseInsensitiveComparator.compare(String.java:1218)
	at java.base/java.util.TreeMap.getEntryUsingComparator(TreeMap.java:374)
	at java.base/java.util.TreeMap.getEntry(TreeMap.java:343)
	at java.base/java.util.TreeMap.get(TreeMap.java:277)
	at org.hibernate.dialect.function.SQLFunctionRegistry.findSQLFunction(SQLFunctionRegistry.java:45)
	at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.findSQLFunction(SessionFactoryHelper.java:385)
	at org.hibernate.hql.internal.ast.tree.IdentNode.getDataType(IdentNode.java:367)
	at org.hibernate.hql.internal.ast.HqlSqlWalker.lookupProperty(HqlSqlWalker.java:667)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.addrExpr(HqlSqlBaseWalker.java:5075)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.addrExprLhs(HqlSqlBaseWalker.java:5783)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.addrExpr(HqlSqlBaseWalker.java:5060)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.expr(HqlSqlBaseWalker.java:1304)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.inRhs(HqlSqlBaseWalker.java:4947)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.comparisonExpr(HqlSqlBaseWalker.java:4561)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2166)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.whereClause(HqlSqlBaseWalker.java:832)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:626)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:330)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:278)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:276)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:192)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73)
	at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162)
	at org.hibernate.query.spi.NamedQueryRepository.checkNamedQueries(NamedQueryRepository.java:159)
	at org.hibernate.internal.SessionFactoryImpl.checkNamedQueries(SessionFactoryImpl.java:570)
	at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:329)
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:468)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1259)
	... 4 more
  1. Added outer classname using $
    query=“SELECT row FROM UserEntity row WHERE auth IN (UserEntity$AUTH.LDAP, UserEntity$AUTH.OAuth)”)
ERROR:  Invalid path: 'UserEntity$AUTH.LDAP'
 Invalid path: 'UserEntity$AUTH.LDAP'
	at org.hibernate.hql.internal.ast.util.LiteralProcessor.lookupConstant(LiteralProcessor.java:111)
  1. Added full package name
    query=“SELECT row FROM UserEntity row WHERE auth IN (com.jamie.test.UserEntity.AUTH.LDAP, com.jamie.test.UserEntity.AUTH.OAuth)”)
ERROR:  Invalid path: 'com.jamie.test.UserEntity.AUTH.LDAP'
 Invalid path: 'com.jamie.test.UserEntity.AUTH.LDAP'
	at org.hibernate.hql.internal.ast.util.LiteralProcessor.lookupConstant(LiteralProcessor.java:111)
  1. Added full package name with query="SELECT row FROM UserEntity row WHERE auth IN (com.jamie.test.UserEntity.AUTH.LDAP, com.jamie.test.UserEntity$AUTH.OAuth)")
ERROR:  Invalid path: 'com.jamie.test.UserEntity$.AUTH.LDAP'
 Invalid path: 'com.jamie.test.UserEntity$.AUTH.LDAP'
	at org.hibernate.hql.internal.ast.util.LiteralProcessor.lookupConstant(LiteralProcessor.java:111)

  1. Moved enum to top level class, outside of Entity class:
    query=“SELECT row FROM UserEntity row WHERE auth IN (com.jamie.test.AUTH.LDAP, com.jamie.test.AUTH.OAuth)”)
ERROR:  Invalid path: 'com.jamie.test.AUTH.LDAP'
 Invalid path: 'com.jamie.test.AUTH.LDAP'
	at org.hibernate.hql.internal.ast.util.LiteralProcessor.lookupConstant(LiteralProcessor.java:111)

Next I will try reverting through versions with the working 5.1 code and see when it broke.

I see I messed up test 6. Here it is again:

query="SELECT row FROM UserEntity row WHERE auth IN (com.jamie.test.UserEntity$AUTH.LDAP, com.jamie.test.UserEntity$AUTH.OAuth)")

ERROR:  Invalid path: 'com.jamie.test.UserEntity$AUTH.LDAP'
 Invalid path: 'com.jamie.test.UserEntity$AUTH.LDAP'
	at org.hibernate.hql.internal.ast.util.LiteralProcessor.lookupConstant(LiteralProcessor.java:111)

Going back to 5.1, the following works:

query="SELECT row FROM UserEntity row WHERE auth_method IN ( com.jamie.test.UserEntity$AUTH.LDAP )")

Can you use your test 6 and debug into org.hibernate.internal.util.ReflectHelper#getConstantValue. I’m curious why it returns null from that method for your constant.

Hello,
Thanks for helping me with this!!!

At getConstantValue():

		try {
			if ( conventionalJavaConstants &&
				!JAVA_CONSTANT_PATTERN.matcher( name ).find() ) {
				return null;
			}

convetionalsJavaConstants=true
name=com.jamie.test.UserEntity$AUTH.LDAP
The REGEX test fails, and the method returns null.

Playing around with that regex in regex101.com
Java string:

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

Un-escaped:

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

The first part looks okay.

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

However, the next term

\.

means that the match fails.

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

Changing my enum name from AUTH to Auth allows the regex to succeed, and my test to complete.

Variations that match the regex:

com.jamie.test.UserEntity$Auth.LDAP
com.jamie.test.UserEntity$Auth.Ldap
com.jamie.test.Userentity$Auth.Ldap
123test.UserEntity$Auth.Ldap

Non-matching variations:

com.jamie.test.UserEntity$Auth.ldap - enum constant 'LDAP' must start with cap
com.jamie.test.userEntity$Auth.Ldap - containing class 'UserEntity' must start with cap
com.jamie.test.Userentity$AUth.Ldap - enum class 'Auth' cannot have more than one cap
com.jamie.test.UserEntity$auth.LDAP - enum class 'Auth' must start with a cap
com.jamie.test.UserEntity$A.Ldap - enum class 'Auth' must have more than one letter
UserEntity$Auth.Ldap - Entity must have a package name

Okay, that last one is arguable. However, I would like to suggest that this regex is too restrictive!

One possible change would be to make the pattern case insensitive:

Pattern JAVA_CONSTANT_PATTERN = Pattern.compile(
				"[a-z\\d]+\\.([a-z]+[a-z\\d]+)+\\$?([a-z]{1}[a-z\\d]+)*\\.[a-z_\\$]+", Pattern.UNICODE_CHARACTER_CLASS | Pattern.CASE_INSENSITIVE);

That regex pattern JAVA_CONSTANT_PATTERN is only used in getConstantValue(
Changing it to case-insensitive, however, might mean that things are getting past that shouldn’t. For example, com.jamie.t matches.

I might even go so far as to suggest that this test is not necessary, as the call to classForName() will presumably barf :

		try {
			if ( conventionalJavaConstants &&
				!JAVA_CONSTANT_PATTERN.matcher( name ).find() ) {
				return null;
			}
			ClassLoaderService classLoaderService = factory.getServiceRegistry().getService( ClassLoaderService.class );
			clazz = classLoaderService.classForName( StringHelper.qualifier( name ) );
		}
		catch ( Throwable t ) {
			return null;
		}

Thanks very much!

Jamie

Hey Jamie,

all this is fixed in Hibernate 6.0 already and I’d rather not touch this in 5.x, so I hope you understand and go with the more common naming for classes.

Hi,
I have renamed my stuff to match the Regex.
I would like to point out that this does not exactly match the java naming convention, as the following enum will not work:
com.test.UserEntity$AuthMethod

Anyway, looking forward to the release of Hibernate 6.
Thanks again,
Jamie.

1 Like