diff --git a/hibernate-core/src/main/java/org/hibernate/SessionFactory.java b/hibernate-core/src/main/java/org/hibernate/SessionFactory.java index c725443c3403..c03e63bd2ad7 100644 --- a/hibernate-core/src/main/java/org/hibernate/SessionFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/SessionFactory.java @@ -506,8 +506,8 @@ default RootGraph createEntityGraph(Class entityType) { RootGraph> createGraphForDynamicEntity(String entityName); /** - * Creates a RootGraph for the given {@code rootEntityClass} and parses the graph text into - * it. + * Creates a {@link RootGraph} for the given {@code rootEntityClass} and parses the + * graph text into it. * * @param rootEntityClass The entity class to use as the base of the created root-graph * @param graphText The textual representation of the graph @@ -527,8 +527,8 @@ default RootGraph parseEntityGraph(Class rootEntityClass, CharSequence } /** - * Creates a RootGraph for the given {@code rootEntityName} and parses the graph text into - * it. + * Creates a {@link RootGraph} for the given {@code rootEntityName} and parses the graph + * text into it. * * @param rootEntityName The name of the entity to use as the base of the created root-graph * @param graphText The textual representation of the graph @@ -548,7 +548,7 @@ default RootGraph parseEntityGraph(String rootEntityName, CharSequence gr } /** - * Creates a RootGraph based on the passed string representation. Here, the + * Creates a {@link RootGraph} based on the passed string representation. Here, the * string representation is expected to include the root entity name. * * @param graphText The textual representation of the graph @@ -565,7 +565,7 @@ default RootGraph parseEntityGraph(CharSequence graphText) { } /** - * Obtain the set of names of all {@link org.hibernate.annotations.FilterDef + * Obtain the set of names of all {@linkplain org.hibernate.annotations.FilterDef * defined filters}. * * @return The set of filter names given by @@ -588,7 +588,7 @@ default RootGraph parseEntityGraph(CharSequence graphText) { FilterDefinition getFilterDefinition(String filterName) throws HibernateException; /** - * Obtain the set of names of all {@link org.hibernate.annotations.FetchProfile + * Obtain the set of names of all {@linkplain org.hibernate.annotations.FetchProfile * defined fetch profiles}. * * @return The set of fetch profile names given by diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java index 7a878f70e61a..f8200fd0b5d8 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -641,9 +641,9 @@ public SqlStringGenerationContext getSqlStringGenerationContext() { return sqlStringGenerationContext; } - @Override @SuppressWarnings({"rawtypes","unchecked"}) + @Override public List> findEntityGraphsByType(Class entityClass) { - return (List) getJpaMetamodel().findEntityGraphsByJavaType( entityClass ); + return getJpaMetamodel().findEntityGraphsByJavaType( entityClass ); } // todo : (5.2) review synchronizationType, persistenceContextType, transactionType usage @@ -928,7 +928,7 @@ public T unwrap(Class type) { @Override public void addNamedEntityGraph(String graphName, EntityGraph entityGraph) { - getMappingMetamodel().addNamedEntityGraph( graphName, (RootGraphImplementor) entityGraph ); + getJpaMetamodel().addNamedEntityGraph( graphName, (RootGraphImplementor) entityGraph ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/MappingMetamodel.java b/hibernate-core/src/main/java/org/hibernate/metamodel/MappingMetamodel.java index 12a0af57c1c0..f939e38819d3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/MappingMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/MappingMetamodel.java @@ -4,17 +4,14 @@ */ package org.hibernate.metamodel; -import java.util.List; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Stream; import org.hibernate.Incubating; import org.hibernate.Internal; -import org.hibernate.graph.RootGraph; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.MappingModelExpressible; -import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; @@ -164,22 +161,6 @@ public interface MappingMetamodel extends Metamodel { */ CollectionPersister findCollectionDescriptor(String role); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // JPA entity graphs - - RootGraph findNamedGraph(String name); - void addNamedEntityGraph(String graphName, RootGraph entityGraph); - void forEachNamedGraph(Consumer> action); - RootGraph defaultGraph(String entityName); - RootGraph defaultGraph(Class entityJavaType); - RootGraph defaultGraph(EntityPersister entityDescriptor); - RootGraph defaultGraph(EntityDomainType entityDomainType); - - List> findRootGraphsForType(Class baseEntityJavaType); - List> findRootGraphsForType(String baseEntityName); - List> findRootGraphsForType(EntityPersister baseEntityDescriptor); - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // SQM model -> Mapping model diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/InjectionHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/InjectionHelper.java index 4f335f63ffc4..04dc1749920d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/InjectionHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/InjectionHelper.java @@ -9,12 +9,12 @@ import org.hibernate.boot.query.NamedQueryDefinition; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.ReflectHelper; -import org.hibernate.metamodel.model.domain.JpaMetamodel; +import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import java.lang.reflect.Field; import static java.lang.Character.charCount; +import static java.lang.Character.isJavaIdentifierPart; public class InjectionHelper { private static final CoreMessageLogger log = CoreLogging.messageLogger( MetadataContext.class ); @@ -22,15 +22,13 @@ public class InjectionHelper { public static void injectEntityGraph( NamedEntityGraphDefinition definition, Class metamodelClass, - JpaMetamodel jpaMetamodel) { + JpaMetamodelImplementor jpaMetamodel) { if ( metamodelClass != null ) { + final String name = definition.name(); + final String fieldName = '_' + javaIdentifier( name ); + final var graph = jpaMetamodel.findEntityGraphByName( name ); try { - injectField( - metamodelClass, - '_' + javaIdentifier( definition.name() ), - jpaMetamodel.findEntityGraphByName( definition.name() ), - false - ); + injectField( metamodelClass, fieldName, graph, false ); } catch ( NoSuchFieldException e ) { // ignore @@ -40,13 +38,10 @@ public static void injectEntityGraph( public static void injectTypedQueryReference(NamedQueryDefinition definition, Class metamodelClass) { if ( metamodelClass != null ) { + final String fieldName = + '_' + javaIdentifier( definition.getRegistrationName() ) + '_'; try { - injectField( - metamodelClass, - '_' + javaIdentifier( definition.getRegistrationName() ) + '_', - definition, - false - ); + injectField( metamodelClass, fieldName, definition, false ); } catch ( NoSuchFieldException e ) { // ignore @@ -59,12 +54,7 @@ public static String javaIdentifier(String name) { int position = 0; while ( position < name.length() ) { final int codePoint = name.codePointAt( position ); - if ( Character.isJavaIdentifierPart(codePoint) ) { - result.appendCodePoint( codePoint ); - } - else { - result.append('_'); - } + result.appendCodePoint( isJavaIdentifierPart( codePoint ) ? codePoint : '_' ); position += charCount( codePoint ); } return result.toString(); @@ -74,12 +64,13 @@ public static void injectField( Class metamodelClass, String name, Object model, boolean allowNonDeclaredFieldReference) throws NoSuchFieldException { - final Field field = allowNonDeclaredFieldReference - ? metamodelClass.getField(name) - : metamodelClass.getDeclaredField(name); + final Field field = + allowNonDeclaredFieldReference + ? metamodelClass.getField( name ) + : metamodelClass.getDeclaredField( name ); try { // should be public anyway, but to be sure... - ReflectHelper.ensureAccessibility( field ); +// ReflectHelper.ensureAccessibility( field ); field.set( null, model); } catch (IllegalAccessException e) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/JpaMetamodelPopulationSetting.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/JpaMetamodelPopulationSetting.java index c95e862ded21..9af807ecaf9a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/JpaMetamodelPopulationSetting.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/JpaMetamodelPopulationSetting.java @@ -26,10 +26,10 @@ public static JpaMetamodelPopulationSetting parse(String setting) { }; } - public static JpaMetamodelPopulationSetting determineJpaMetaModelPopulationSetting(Map configurationValues) { + public static JpaMetamodelPopulationSetting determineJpaMetaModelPopulationSetting(Map settings) { String setting = ConfigurationHelper.getString( AvailableSettings.JPA_METAMODEL_POPULATION, - configurationValues, + settings, "ignoreUnsupported" ); return JpaMetamodelPopulationSetting.parse( setting ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/DomainType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/DomainType.java index df86c5bcf226..1b00124a2524 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/DomainType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/DomainType.java @@ -14,7 +14,7 @@ *

* Encapsulates a {@link JavaType} describing the more rudimentary aspects * of the Java type. The {@code DomainType} is a higher-level construct - * incorporating information such as bean properties, constructors, etc. + * incorporating information such as bean properties, constructors, and so on. * * @implNote The actual JPA type system is more akin to {@link SimpleDomainType}. * This contract represents a "higher level" abstraction, allowing diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java index bacf2ee33ca7..ca496516c904 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/JpaMetamodel.java @@ -4,16 +4,12 @@ */ package org.hibernate.metamodel.model.domain; -import java.util.List; -import java.util.Map; import java.util.Set; -import jakarta.persistence.EntityGraph; import jakarta.persistence.metamodel.Metamodel; import org.checkerframework.checker.nullness.qual.Nullable; import org.hibernate.Incubating; -import org.hibernate.graph.RootGraph; import org.hibernate.metamodel.MappingMetamodel; import org.hibernate.type.descriptor.java.EnumJavaType; import org.hibernate.type.descriptor.java.JavaType; @@ -100,6 +96,9 @@ public interface JpaMetamodel extends Metamodel { String qualifyImportableName(String queryName); + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Enumerations and Java constants (useful for interpreting HQL) + @Nullable Set getEnumTypesForValue(String enumValue); EnumJavaType getEnumType(String className); @@ -122,15 +121,4 @@ public interface JpaMetamodel extends Metamodel { @Override EmbeddableDomainType embeddable(Class cls); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Entity graphs - - void addNamedEntityGraph(String graphName, RootGraph entityGraph); - - RootGraph findEntityGraphByName(String name); - - List> findEntityGraphsByJavaType(Class entityClass); - - Map> getNamedEntityGraphs(Class entityType); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java index bbe5ae61c501..01bf7fd6b2a3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java @@ -27,7 +27,6 @@ import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.graph.RootGraph; import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; @@ -355,8 +354,7 @@ public JavaType getJavaConstantType(String className, String fieldName) { try { final Field referencedField = getJavaField( className, fieldName ); if ( referencedField != null ) { - return getTypeConfiguration() - .getJavaTypeRegistry() + return getTypeConfiguration().getJavaTypeRegistry() .getDescriptor( referencedField.getType() ); } } @@ -387,11 +385,10 @@ private Field getJavaField(String className, String fieldName) throws NoSuchFiel } @Override - public void addNamedEntityGraph(String graphName, RootGraph entityGraph) { - final RootGraphImplementor rootGraph = (RootGraphImplementor) entityGraph; + public void addNamedEntityGraph(String graphName, RootGraphImplementor rootGraph) { final EntityGraph old = entityGraphMap.put( graphName, rootGraph.makeImmutableCopy( graphName ) ); if ( old != null ) { - log.debugf( "EntityGraph being replaced on EntityManagerFactory for name %s", graphName ); + log.debugf( "EntityGraph named '%s' was replaced", graphName ); } } @@ -401,13 +398,13 @@ public RootGraphImplementor findEntityGraphByName(String name) { } @Override - public List> findEntityGraphsByJavaType(Class entityClass) { + public List> findEntityGraphsByJavaType(Class entityClass) { final EntityDomainType entityType = entity( entityClass ); if ( entityType == null ) { throw new IllegalArgumentException( "Given class is not an entity: " + entityClass.getName() ); } else { - final List> results = new ArrayList<>(); + final List> results = new ArrayList<>(); for ( var entityGraph : entityGraphMap.values() ) { if ( entityGraph.appliesTo( entityType ) ) { @SuppressWarnings("unchecked") // safe, we just checked diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappingMetamodelImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappingMetamodelImpl.java index 30571856fe48..72326af1c28b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappingMetamodelImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappingMetamodelImpl.java @@ -7,7 +7,6 @@ import java.io.Serializable; import java.util.Arrays; import java.util.HashSet; -import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; @@ -22,7 +21,6 @@ import org.hibernate.UnknownEntityTypeException; import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.cache.spi.CacheImplementor; -import org.hibernate.graph.RootGraph; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.collections.ArrayHelper; @@ -68,7 +66,6 @@ import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.spi.TypeConfiguration; -import jakarta.persistence.EntityGraph; import jakarta.persistence.metamodel.EmbeddableType; import jakarta.persistence.metamodel.EntityType; import jakarta.persistence.metamodel.ManagedType; @@ -561,71 +558,6 @@ public CollectionPersister findCollectionDescriptor(String role) { return collectionPersisterMap.get( role ); } - @Override - public void addNamedEntityGraph(String graphName, RootGraph entityGraph) { - jpaMetamodel.addNamedEntityGraph( graphName, entityGraph ); - } - - @Override - public RootGraph findEntityGraphByName(String name) { - return jpaMetamodel.findEntityGraphByName( name ); - } - - @Override - public Map> getNamedEntityGraphs(Class entityType) { - return jpaMetamodel.getNamedEntityGraphs( entityType ); - } - - @Override - public List> findEntityGraphsByJavaType(Class entityClass) { - return jpaMetamodel.findEntityGraphsByJavaType( entityClass ); - } - - @Override - public RootGraph findNamedGraph(String name) { - return findEntityGraphByName( name ); - } - - @Override - public void forEachNamedGraph(Consumer> action) { - throw new UnsupportedOperationException(); - } - - @Override - public RootGraph defaultGraph(String entityName) { - throw new UnsupportedOperationException(); - } - - @Override - public RootGraph defaultGraph(Class entityJavaType) { - throw new UnsupportedOperationException(); - } - - @Override - public RootGraph defaultGraph(EntityPersister entityDescriptor) { - throw new UnsupportedOperationException(); - } - - @Override - public RootGraph defaultGraph(EntityDomainType entityDomainType) { - return null; - } - - @Override - public List> findRootGraphsForType(Class baseEntityJavaType) { - throw new UnsupportedOperationException(); - } - - @Override - public List> findRootGraphsForType(String baseEntityName) { - throw new UnsupportedOperationException(); - } - - @Override - public List> findRootGraphsForType(EntityPersister baseEntityDescriptor) { - return null; - } - @Override public MappingModelExpressible resolveMappingExpressible( SqmExpressible sqmExpressible, diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/spi/JpaMetamodelImplementor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/spi/JpaMetamodelImplementor.java index ff8eb366fd4a..82f2db466dec 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/spi/JpaMetamodelImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/spi/JpaMetamodelImplementor.java @@ -4,10 +4,14 @@ */ package org.hibernate.metamodel.model.domain.spi; +import jakarta.persistence.EntityGraph; import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.metamodel.MappingMetamodel; import org.hibernate.metamodel.model.domain.JpaMetamodel; +import java.util.List; +import java.util.Map; + /** * SPI extending {@link JpaMetamodel}. * @@ -16,6 +20,9 @@ public interface JpaMetamodelImplementor extends JpaMetamodel { MappingMetamodel getMappingMetamodel(); - @Override RootGraphImplementor findEntityGraphByName(String name); + void addNamedEntityGraph(String graphName, RootGraphImplementor rootGraph); + + List> findEntityGraphsByJavaType(Class entityClass); + Map> getNamedEntityGraphs(Class entityClass); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/BasicDotIdentifierConsumer.java b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/BasicDotIdentifierConsumer.java index 0bc8da3f5df2..8ffb373337cc 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/BasicDotIdentifierConsumer.java +++ b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/BasicDotIdentifierConsumer.java @@ -7,11 +7,11 @@ import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.query.SemanticException; -import org.hibernate.query.hql.HqlLogging; import org.hibernate.query.hql.spi.DotIdentifierConsumer; import org.hibernate.query.hql.spi.SemanticPathPart; import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.hql.spi.SqmPathRegistry; +import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.function.SqmFunctionDescriptor; import org.hibernate.query.sqm.spi.SqmCreationContext; @@ -27,6 +27,8 @@ import org.hibernate.type.descriptor.java.EnumJavaType; import org.hibernate.type.descriptor.java.JavaType; +import static org.hibernate.query.hql.HqlLogging.QUERY_LOGGER; + /** * A {@link DotIdentifierConsumer} used to interpret paths outside any * specific context. This is the handler used at the root of the handler @@ -78,7 +80,7 @@ public void consumeIdentifier(String identifier, boolean isBase, boolean isTermi } pathSoFar.append( identifier ); - HqlLogging.QUERY_LOGGER.tracef( + QUERY_LOGGER.tracef( "BasicDotIdentifierHandler#consumeIdentifier( %s, %s, %s ) - %s", identifier, isBase, @@ -119,7 +121,7 @@ public SemanticPathPart resolvePathPart( String identifier, boolean isTerminal, SqmCreationState creationState) { - HqlLogging.QUERY_LOGGER.tracef( + QUERY_LOGGER.tracef( "BaseLocalSequencePart#consumeIdentifier( %s, %s, %s ) - %s", identifier, isBase, @@ -129,50 +131,89 @@ public SemanticPathPart resolvePathPart( if ( isBase ) { isBase = false; - - final SqmPathRegistry sqmPathRegistry = - creationState.getProcessingStateStack().getCurrent() - .getPathRegistry(); - - final SqmFrom pathRootByAlias = sqmPathRegistry.findFromByAlias( identifier, true ); - if ( pathRootByAlias != null ) { - // identifier is an alias (identification variable) - validateAsRoot( pathRootByAlias ); - return isTerminal ? pathRootByAlias : new DomainPathPart( pathRootByAlias ); - } - - final SqmFrom pathRootByExposedNavigable = sqmPathRegistry.findFromExposing( identifier ); - if ( pathRootByExposedNavigable != null ) { - // identifier is an "unqualified attribute reference" - validateAsRoot( pathRootByExposedNavigable ); - final SqmPath sqmPath = pathRootByExposedNavigable.get( identifier, true ); - return isTerminal ? sqmPath : new DomainPathPart( sqmPath ); + final SemanticPathPart pathPart = + resolvePath( identifier, isTerminal, creationState ); + if ( pathPart != null ) { + return pathPart; } } - // at the moment, below this point we wait to resolve the sequence until we hit the terminal - // - // we could check for "intermediate resolution", but that comes with a performance hit. E.g., consider + // Below this point we wait to resolve the sequence until we hit the terminal. + // We could check for "intermediate resolution", but that comes with a performance hit. + // Consider: // - // `org.hibernate.test.Sex.MALE` + // org.hibernate.test.Sex.MALE // - // we could check `org` and then `org.hibernate` and then `org.hibernate.test` and then ... until - // we know it is a package, class or entity name. That gets expensive though. For now, plan on - // resolving these at the terminal - // - // todo (6.0) : finish this logic. and see above note in `! isTerminal` block - + // We could check 'org', then 'org.hibernate', then 'org.hibernate.test' and so on until + // we know it's a package, class or entity name. That's more expensive though, and the + // error message would not be better. - if ( ! isTerminal ) { - return this; - } + return isTerminal ? resolveTerminal( creationState ) : this; + } + private SemanticPathPart resolveTerminal(SqmCreationState creationState) { final SqmCreationContext creationContext = creationState.getCreationContext(); - final JpaMetamodel jpaMetamodel = creationContext.getJpaMetamodel(); - final String path = pathSoFar.toString(); - final String importableName = jpaMetamodel.qualifyImportableName( path ); final NodeBuilder nodeBuilder = creationContext.getNodeBuilder(); - if ( importableName != null ) { + final JpaMetamodel jpaMetamodel = creationContext.getJpaMetamodel(); + final QueryEngine queryEngine = creationContext.getQueryEngine(); + + final SemanticPathPart literalType = + resolveLiteralType( jpaMetamodel, nodeBuilder ); + if ( literalType != null ) { + return literalType; + } + + final SqmFunctionDescriptor functionDescriptor = + resolveFunction( queryEngine ); + if ( functionDescriptor != null ) { + return functionDescriptor.generateSqmExpression( null, queryEngine ); + } + + final SemanticPathPart literalJava = + resolveLiteralJavaElement( jpaMetamodel, nodeBuilder ); + if ( literalJava != null ) { + return literalJava; + } + + throw new SemanticException( "Could not interpret path expression '" + pathSoFar + "'" ); + } + + private SemanticPathPart resolvePath(String identifier, boolean isTerminal, SqmCreationState creationState) { + final SqmPathRegistry sqmPathRegistry = + creationState.getProcessingStateStack().getCurrent() + .getPathRegistry(); + + final SqmFrom pathRootByAlias = + sqmPathRegistry.findFromByAlias( identifier, true ); + if ( pathRootByAlias != null ) { + // identifier is an alias (identification variable) + validateAsRoot( pathRootByAlias ); + return isTerminal ? pathRootByAlias : new DomainPathPart( pathRootByAlias ); + } + + final SqmFrom pathRootByExposedNavigable = + sqmPathRegistry.findFromExposing( identifier ); + if ( pathRootByExposedNavigable != null ) { + // identifier is an "unqualified attribute reference" + validateAsRoot( pathRootByExposedNavigable ); + final SqmPath sqmPath = + pathRootByExposedNavigable.get( identifier, true ); + return isTerminal ? sqmPath : new DomainPathPart( sqmPath ); + } + + return null; + } + + private SqmFunctionDescriptor resolveFunction(QueryEngine queryEngine) { + return queryEngine.getSqmFunctionRegistry().findFunctionDescriptor( pathSoFar.toString() ); + } + + private SemanticPathPart resolveLiteralType(JpaMetamodel jpaMetamodel, NodeBuilder nodeBuilder) { + final String importableName = jpaMetamodel.qualifyImportableName( pathSoFar.toString() ); + if ( importableName == null ) { + return null; + } + else { final ManagedDomainType managedType = jpaMetamodel.managedType( importableName ); if ( managedType instanceof SqmEntityDomainType entityDomainType ) { return new SqmLiteralEntityType<>( entityDomainType, nodeBuilder ); @@ -180,36 +221,34 @@ public SemanticPathPart resolvePathPart( else if ( managedType instanceof SqmEmbeddableDomainType embeddableDomainType ) { return new SqmLiteralEmbeddableType<>( embeddableDomainType, nodeBuilder ); } + else { + return null; + } } + } - final SqmFunctionDescriptor functionDescriptor = - creationContext.getQueryEngine().getSqmFunctionRegistry() - .findFunctionDescriptor( path ); - if ( functionDescriptor != null ) { - return functionDescriptor.generateSqmExpression( null, creationContext.getQueryEngine() ); - } - + private SemanticPathPart resolveLiteralJavaElement(JpaMetamodel metamodel, NodeBuilder nodeBuilder) { + final String path = pathSoFar.toString(); // see if it is a named field/enum reference final int splitPosition = path.lastIndexOf( '.' ); if ( splitPosition > 0 ) { final String prefix = path.substring( 0, splitPosition ); final String terminal = path.substring( splitPosition + 1 ); try { - final EnumJavaType enumType = jpaMetamodel.getEnumType( prefix ); + final EnumJavaType enumType = metamodel.getEnumType( prefix ); if ( enumType != null ) { - return sqmEnumLiteral( jpaMetamodel, enumType, terminal, nodeBuilder ); + return sqmEnumLiteral( metamodel, enumType, terminal, nodeBuilder ); } - final JavaType fieldJtdTest = jpaMetamodel.getJavaConstantType( prefix, terminal ); + final JavaType fieldJtdTest = metamodel.getJavaConstantType( prefix, terminal ); if ( fieldJtdTest != null ) { - return sqmFieldLiteral( jpaMetamodel, prefix, terminal, fieldJtdTest, nodeBuilder ); + return sqmFieldLiteral( metamodel, prefix, terminal, fieldJtdTest, nodeBuilder ); } } catch (Exception ignore) { } } - - throw new SemanticException( "Could not interpret path expression '" + path + "'" ); + return null; } private static SqmFieldLiteral sqmFieldLiteral( diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmJpaCriteriaParameterWrapper.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmJpaCriteriaParameterWrapper.java index 2daad8a02939..a1c702037954 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmJpaCriteriaParameterWrapper.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmJpaCriteriaParameterWrapper.java @@ -124,8 +124,8 @@ public void appendHqlString(StringBuilder hql, SqmRenderContext context) { @Override public int compareTo(SqmParameter anotherParameter) { - return anotherParameter instanceof SqmJpaCriteriaParameterWrapper ? - getJpaCriteriaParameter().compareTo( ( (SqmJpaCriteriaParameterWrapper) anotherParameter ).getJpaCriteriaParameter() ) + return anotherParameter instanceof SqmJpaCriteriaParameterWrapper parameterWrapper + ? getJpaCriteriaParameter().compareTo( parameterWrapper.getJpaCriteriaParameter() ) : 1; } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmNamedParameter.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmNamedParameter.java index 454fab3642b8..f050c26b27d1 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmNamedParameter.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmNamedParameter.java @@ -83,8 +83,8 @@ public void appendHqlString(StringBuilder hql, SqmRenderContext context) { @Override public int compareTo(SqmParameter anotherParameter) { - return anotherParameter instanceof SqmNamedParameter - ? getName().compareTo( ( (SqmNamedParameter) anotherParameter ).getName() ) + return anotherParameter instanceof SqmNamedParameter sqmNamedParameter + ? getName().compareTo( sqmNamedParameter.getName() ) : -1; } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmPositionalParameter.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmPositionalParameter.java index 0990a6f18452..ee3baa3820b5 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmPositionalParameter.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmPositionalParameter.java @@ -86,8 +86,8 @@ public void appendHqlString(StringBuilder hql, SqmRenderContext context) { @Override public int compareTo(SqmParameter anotherParameter) { - return anotherParameter instanceof SqmPositionalParameter - ? getPosition().compareTo( ( (SqmPositionalParameter) anotherParameter ).getPosition() ) + return anotherParameter instanceof SqmPositionalParameter sqmPositionalParameter + ? getPosition().compareTo( sqmPositionalParameter.getPosition() ) : 1; } }