From 1074891a360a073298577e8c2fa17e035ae261c4 Mon Sep 17 00:00:00 2001 From: Gavin Date: Wed, 4 Jan 2023 01:50:18 +0100 Subject: [PATCH] migrate to accessing QueryParameterBindingTypeResolver via MappingMetamodelImplementor it's just not elegant to have it as a supertype of SessionFactoryImplementor (so deprecate that) --- .../java/org/hibernate/dialect/Dialect.java | 4 +- .../spi/SessionFactoryDelegatingImpl.java | 4 +- .../engine/spi/SessionFactoryImplementor.java | 16 +- ...QueryParameterBindingTypeResolverImpl.java | 63 ++++ .../internal/SessionFactoryImpl.java | 38 +-- .../domain/internal/MappingMetamodelImpl.java | 9 +- .../spi/MappingMetamodelImplementor.java | 5 +- .../procedure/internal/ProcedureCallImpl.java | 4 +- .../internal/QueryParameterBindingImpl.java | 4 +- .../spi/AbstractCommonQueryContract.java | 2 +- .../org/hibernate/query/spi/QueryEngine.java | 312 ++++++++---------- .../query/spi/QueryEngineOptions.java | 3 + .../QueryParameterBindingTypeResolver.java | 10 +- .../sqm/internal/SqmCriteriaNodeBuilder.java | 52 ++- .../exec/internal/AbstractJdbcParameter.java | 6 +- 15 files changed, 267 insertions(+), 265 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/internal/QueryParameterBindingTypeResolverImpl.java diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java index 2e5ed12945..a8ce03ece0 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -1029,7 +1029,9 @@ public abstract class Dialect implements ConversionContext { "cast", new CastFunction( this, - queryEngine.getPreferredSqlTypeCodeForBoolean() + queryEngine.getTypeConfiguration() + .getCurrentBaseSqlTypeIndicators() + .getPreferredSqlTypeCodeForBoolean() ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionFactoryDelegatingImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionFactoryDelegatingImpl.java index 65cdb74f1b..5b3a3e187c 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionFactoryDelegatingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionFactoryDelegatingImpl.java @@ -349,12 +349,12 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor, return delegate.isOpen(); } - @Override + @Override @Deprecated public BindableType resolveParameterBindType(T bindValue) { return delegate.resolveParameterBindType( bindValue ); } - @Override + @Override @Deprecated public BindableType resolveParameterBindType(Class clazz) { return delegate.resolveParameterBindType( clazz ); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionFactoryImplementor.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionFactoryImplementor.java index 33e09ad72c..9e5c5b75b2 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionFactoryImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionFactoryImplementor.java @@ -25,6 +25,7 @@ import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.metamodel.spi.MetamodelImplementor; import org.hibernate.metamodel.spi.RuntimeMetamodelsImplementor; import org.hibernate.proxy.EntityNotFoundDelegate; +import org.hibernate.query.BindableType; import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryParameterBindingTypeResolver; @@ -47,7 +48,8 @@ import org.hibernate.type.spi.TypeConfiguration; * @author Steve Ebersole */ public interface SessionFactoryImplementor - extends Mapping, SessionFactory, SqmCreationContext, SqlAstCreationContext, QueryParameterBindingTypeResolver { + extends Mapping, SessionFactory, SqmCreationContext, SqlAstCreationContext, + QueryParameterBindingTypeResolver { //deprecated extension, use MappingMetamodel /** * Get the UUID for this SessionFactory. *

@@ -205,4 +207,16 @@ public interface SessionFactoryImplementor */ String bestGuessEntityName(Object object); + /** + * @deprecated Use {@link #getMappingMetamodel()}.{@link MappingMetamodelImplementor#resolveParameterBindType(Object)} + */ + @Deprecated(since = "6.2", forRemoval = true) + BindableType resolveParameterBindType(T bindValue); + + /** + * @deprecated Use {@link #getMappingMetamodel()}.{@link MappingMetamodelImplementor#resolveParameterBindType(Class)} + */ + @Deprecated(since = "6.2", forRemoval = true) + BindableType resolveParameterBindType(Class clazz); + } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/QueryParameterBindingTypeResolverImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/QueryParameterBindingTypeResolverImpl.java new file mode 100644 index 0000000000..0c6466c757 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/internal/QueryParameterBindingTypeResolverImpl.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.internal; + +import org.hibernate.proxy.LazyInitializer; +import org.hibernate.query.BindableType; +import org.hibernate.query.spi.QueryParameterBindingTypeResolver; + +import java.io.Serializable; + +import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer; + +/** + * @implNote This code was originally in {@link SessionFactoryImpl}, but has been factored out so that it + * can be shared by {@link org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl}, + * which is where it really belongs, IMO. Eventually, we can kill off the subtyping relationship + * between {@link SessionFactoryImpl} and {@link QueryParameterBindingTypeResolver}, and then + * get rid of this class. + * + * @author Gavin King + * + * @since 6.2 + */ +public abstract class QueryParameterBindingTypeResolverImpl implements QueryParameterBindingTypeResolver { + + @Override + public BindableType resolveParameterBindType(Class javaType) { + return getMappingMetamodel().resolveQueryParameterType( javaType ); + } + + @Override + public BindableType resolveParameterBindType(T bindValue) { + if ( bindValue == null ) { + // we can't guess + return null; + } + + final LazyInitializer lazyInitializer = extractLazyInitializer( bindValue ); + final Class clazz = lazyInitializer != null ? lazyInitializer.getPersistentClass() : bindValue.getClass(); + + // Resolve superclass bindable type if necessary, as we don't register types for e.g. Inet4Address + Class c = clazz; + do { + final BindableType type = resolveParameterBindType( c ); + if ( type != null ) { + //noinspection unchecked + return (BindableType) type; + } + c = c.getSuperclass(); + } + while ( c != Object.class ); + if ( !clazz.isEnum() && Serializable.class.isAssignableFrom( clazz ) ) { + //noinspection unchecked + return (BindableType) resolveParameterBindType( Serializable.class ); + } + return null; + } + +} 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 34db85b6b3..9a3bd7e2b9 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -10,7 +10,6 @@ import java.io.IOException; import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.io.Serializable; import java.sql.Connection; import java.util.ArrayList; import java.util.Collections; @@ -77,7 +76,6 @@ import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.RootClass; import org.hibernate.metadata.CollectionMetadata; -import org.hibernate.metamodel.MappingMetamodel; import org.hibernate.metamodel.internal.RuntimeMetamodelsImpl; import org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl; import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; @@ -89,7 +87,6 @@ import org.hibernate.persister.entity.SessionFactoryBasedWrapperOptions; import org.hibernate.procedure.spi.ProcedureCallImplementor; import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.proxy.LazyInitializer; -import org.hibernate.query.BindableType; import org.hibernate.query.hql.spi.SqmQueryImplementor; import org.hibernate.query.named.NamedObjectRepository; import org.hibernate.query.named.NamedQueryMemento; @@ -154,7 +151,7 @@ import static org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode.DEL * @author Steve Ebersole * @author Chris Cranford */ -public class SessionFactoryImpl implements SessionFactoryImplementor { +public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl implements SessionFactoryImplementor { private static final CoreMessageLogger LOG = CoreLogging.messageLogger( SessionFactoryImpl.class ); private final String name; @@ -1118,39 +1115,6 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { return fetchProfiles.get( name ); } - @Override - public BindableType resolveParameterBindType(T bindValue) { - if ( bindValue == null ) { - // we can't guess - return null; - } - - final LazyInitializer lazyInitializer = extractLazyInitializer( bindValue ); - final Class clazz = lazyInitializer != null ? lazyInitializer.getPersistentClass() : bindValue.getClass(); - - // Resolve superclass bindable type if necessary, as we don't register types for e.g. Inet4Address - Class c = clazz; - do { - final BindableType type = resolveParameterBindType( c ); - if ( type != null ) { - //noinspection unchecked - return (BindableType) type; - } - c = c.getSuperclass(); - } - while ( c != Object.class ); - if ( !clazz.isEnum() && Serializable.class.isAssignableFrom( clazz ) ) { - //noinspection unchecked - return (BindableType) resolveParameterBindType( Serializable.class ); - } - return null; - } - - @Override - public BindableType resolveParameterBindType(Class javaType) { - return getRuntimeMetamodels().getMappingMetamodel().resolveQueryParameterType( javaType ); - } - /** * @deprecated use {@link #configuredInterceptor(Interceptor, boolean, SessionFactoryOptions)} */ 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 0e48fc16f2..80f06289bf 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 @@ -34,6 +34,7 @@ import org.hibernate.graph.RootGraph; import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.internal.EntityManagerMessageLogger; import org.hibernate.internal.HEMLogging; +import org.hibernate.internal.QueryParameterBindingTypeResolverImpl; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.jpa.spi.JpaCompliance; import org.hibernate.mapping.Collection; @@ -93,7 +94,8 @@ import static org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetti * @author Emmanuel Bernard * @author Andrea Boriero */ -public class MappingMetamodelImpl implements MappingMetamodelImplementor, MetamodelImplementor, Serializable { +public class MappingMetamodelImpl extends QueryParameterBindingTypeResolverImpl + implements MappingMetamodelImplementor, MetamodelImplementor, Serializable { // todo : Integrate EntityManagerLogger into CoreMessageLogger private static final EntityManagerMessageLogger log = HEMLogging.messageLogger( MappingMetamodelImpl.class ); @@ -361,6 +363,11 @@ public class MappingMetamodelImpl implements MappingMetamodelImplementor, Metamo return typeConfiguration; } + @Override + public MappingMetamodel getMappingMetamodel() { + return this; + } + @Override public ServiceRegistry getServiceRegistry() { return serviceRegistry; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MappingMetamodelImplementor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MappingMetamodelImplementor.java index ec611aea20..f10f24952c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MappingMetamodelImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/MappingMetamodelImplementor.java @@ -11,11 +11,12 @@ import java.util.Set; import org.hibernate.EntityNameResolver; import org.hibernate.metamodel.MappingMetamodel; +import org.hibernate.query.spi.QueryParameterBindingTypeResolver; /** * @author Steve Ebersole */ -public interface MappingMetamodelImplementor extends MappingMetamodel { +public interface MappingMetamodelImplementor extends MappingMetamodel, QueryParameterBindingTypeResolver { /** * Retrieves a set of all the collection roles in which the given entity is a participant, as either an @@ -33,6 +34,4 @@ public interface MappingMetamodelImplementor extends MappingMetamodel { */ Collection getEntityNameResolvers(); - - } diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java b/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java index c635fed537..58c31aa96c 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java @@ -488,7 +488,7 @@ public class ProcedureCallImpl @Override public ProcedureParameter registerParameter(int position, Class javaType, ParameterMode mode) { - final BindableType parameterType = getSessionFactory().resolveParameterBindType( javaType ); + final BindableType parameterType = getSessionFactory().getMappingMetamodel().resolveParameterBindType( javaType ); final ProcedureParameterImpl procedureParameter = new ProcedureParameterImpl<>( position, @@ -531,7 +531,7 @@ public class ProcedureCallImpl @Override public ProcedureParameterImplementor registerParameter(String name, Class javaType, ParameterMode mode) { - final BindableType parameterType = getSessionFactory().resolveParameterBindType( javaType ); + final BindableType parameterType = getSessionFactory().getMappingMetamodel().resolveParameterBindType( javaType ); final ProcedureParameterImpl parameter = new ProcedureParameterImpl<>( name, diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingImpl.java b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingImpl.java index f803f486f1..793105a75d 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingImpl.java @@ -174,7 +174,7 @@ public class QueryParameterBindingImpl implements QueryParameterBinding, J if ( bindType == null ) { if ( value != null ) { - this.bindType = sessionFactory.resolveParameterBindType( value ); + this.bindType = sessionFactory.getMappingMetamodel().resolveParameterBindType( value ); } } } @@ -267,7 +267,7 @@ public class QueryParameterBindingImpl implements QueryParameterBinding, J } if ( bindType == null && value != null ) { - this.bindType = sessionFactory.resolveParameterBindType( value ); + this.bindType = sessionFactory.getMappingMetamodel().resolveParameterBindType( value ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java index 48f5d013e5..bd709f511d 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java +++ b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java @@ -1429,7 +1429,7 @@ public abstract class AbstractCommonQueryContract implements CommonQueryContract type = getParameterMetadata().getQueryParameter( namedParam ).getHibernateType(); } if ( type == null && retType != null ) { - type = getSession().getFactory().resolveParameterBindType( retType ); + type = getSession().getFactory().getMappingMetamodel().resolveParameterBindType( retType ); } //noinspection unchecked return (BindableType) type; diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/QueryEngine.java b/hibernate-core/src/main/java/org/hibernate/query/spi/QueryEngine.java index 89450c0ff6..08a2c56183 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/spi/QueryEngine.java +++ b/hibernate-core/src/main/java/org/hibernate/query/spi/QueryEngine.java @@ -18,6 +18,7 @@ import org.hibernate.boot.model.FunctionContributions; import org.hibernate.boot.model.FunctionContributor; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.spi.MetadataImplementor; +import org.hibernate.boot.spi.SessionFactoryOptions; import org.hibernate.cfg.AvailableSettings; import org.hibernate.dialect.Dialect; import org.hibernate.engine.config.spi.ConfigurationService; @@ -25,9 +26,7 @@ import org.hibernate.engine.query.spi.NativeQueryInterpreter; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.jpa.spi.JpaCompliance; import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; -import org.hibernate.query.BindableType; import org.hibernate.query.criteria.ValueHandlingMode; import org.hibernate.query.hql.HqlTranslator; import org.hibernate.query.hql.internal.StandardHqlTranslator; @@ -36,7 +35,6 @@ import org.hibernate.query.internal.QueryInterpretationCacheDisabledImpl; import org.hibernate.query.internal.QueryInterpretationCacheStandardImpl; import org.hibernate.query.named.NamedObjectRepository; import org.hibernate.query.sqm.NodeBuilder; -import org.hibernate.query.sqm.function.SqmFunctionDescriptor; import org.hibernate.query.sqm.function.SqmFunctionRegistry; import org.hibernate.query.sqm.internal.SqmCreationOptionsStandard; import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder; @@ -58,7 +56,7 @@ import static java.util.Comparator.comparingInt; * @author Steve Ebersole */ @Incubating -public class QueryEngine implements QueryParameterBindingTypeResolver { +public class QueryEngine { /** * The default soft reference count. @@ -68,146 +66,91 @@ public class QueryEngine implements QueryParameterBindingTypeResolver { private static final Logger LOG_HQL_FUNCTIONS = CoreLogging.logger( "org.hibernate.HQL_FUNCTIONS" ); public static QueryEngine from(SessionFactoryImplementor sessionFactory, MetadataImplementor metadata) { - final QueryEngineOptions queryEngineOptions = sessionFactory.getSessionFactoryOptions(); + final QueryEngineOptions options = sessionFactory.getSessionFactoryOptions(); final Dialect dialect = sessionFactory.getJdbcServices().getDialect(); return new QueryEngine( sessionFactory, - resolveHqlTranslator( - queryEngineOptions, - dialect, - sessionFactory, - new SqmCreationOptionsStandard( queryEngineOptions ) - ), - resolveSqmTranslatorFactory( queryEngineOptions, dialect ), - metadata, - dialect, - buildCustomFunctionRegistry( queryEngineOptions ) - ); - } - - private static SqmFunctionRegistry buildCustomFunctionRegistry(QueryEngineOptions queryEngineOptions) { - if ( queryEngineOptions.getCustomSqmFunctionRegistry() == null ) { - final Map customSqlFunctionMap = queryEngineOptions.getCustomSqlFunctionMap(); - if ( customSqlFunctionMap == null || customSqlFunctionMap.isEmpty() ) { - return null; - } - else { - SqmFunctionRegistry customSqmFunctionRegistry = new SqmFunctionRegistry(); - customSqlFunctionMap.forEach( customSqmFunctionRegistry::register ); - return customSqmFunctionRegistry; - } - } - else { - return queryEngineOptions.getCustomSqmFunctionRegistry(); - } - } - - private final NamedObjectRepository namedObjectRepository; - private final SqmCriteriaNodeBuilder criteriaBuilder; - private final HqlTranslator hqlTranslator; - private final SqmTranslatorFactory sqmTranslatorFactory; - private final NativeQueryInterpreter nativeQueryInterpreter; - private final QueryInterpretationCache interpretationCache; - private final SqmFunctionRegistry sqmFunctionRegistry; - private final TypeConfiguration typeConfiguration; - private final int preferredSqlTypeCodeForBoolean; - private final QueryParameterBindingTypeResolver queryParameterBindingTypeResolver; - - private QueryEngine( - SessionFactoryImplementor sessionFactory, - HqlTranslator hqlTranslator, - SqmTranslatorFactory sqmTranslatorFactory, - MetadataImplementor metadata, - Dialect dialect, - SqmFunctionRegistry customFunctionRegistry) { - this( - sessionFactory.getUuid(), - sessionFactory.getName(), - sessionFactory.getSessionFactoryOptions().getJpaCompliance(), - () -> sessionFactory.getRuntimeMetamodels().getJpaMetamodel(), - sessionFactory.getSessionFactoryOptions().getCriteriaValueHandlingMode(), - sessionFactory.getSessionFactoryOptions().getPreferredSqlTypeCodeForBoolean(), - metadata.buildNamedQueryRepository( sessionFactory ), - hqlTranslator, - sqmTranslatorFactory, - sessionFactory.getServiceRegistry().getService( NativeQueryInterpreter.class ), - buildInterpretationCache( sessionFactory::getStatistics, sessionFactory.getProperties() ), metadata.getTypeConfiguration(), - dialect, - customFunctionRegistry, - sessionFactory.getServiceRegistry(), - sessionFactory + resolveHqlTranslator( options, dialect, sessionFactory, new SqmCreationOptionsStandard( options ) ), + resolveSqmTranslatorFactory( options, dialect ), + createFunctionRegistry( sessionFactory, metadata, options, dialect ), + metadata.buildNamedQueryRepository( sessionFactory ), + buildInterpretationCache( sessionFactory::getStatistics, sessionFactory.getProperties() ) ); } - private QueryEngine( - String uuid, - String name, - JpaCompliance jpaCompliance, - Supplier jpaMetamodelAccess, - ValueHandlingMode criteriaValueHandlingMode, - int preferredSqlTypeCodeForBoolean, - NamedObjectRepository namedObjectRepository, - HqlTranslator hqlTranslator, - SqmTranslatorFactory sqmTranslatorFactory, - NativeQueryInterpreter nativeQueryInterpreter, - QueryInterpretationCache interpretationCache, - TypeConfiguration typeConfiguration, - Dialect dialect, - SqmFunctionRegistry userDefinedRegistry, - ServiceRegistry serviceRegistry, - SessionFactoryImplementor sessionFactory) { - this.queryParameterBindingTypeResolver = sessionFactory; - this.namedObjectRepository = Objects.requireNonNull( namedObjectRepository ); - this.sqmTranslatorFactory = sqmTranslatorFactory; - this.nativeQueryInterpreter = Objects.requireNonNull( nativeQueryInterpreter ); - this.interpretationCache = interpretationCache; - this.hqlTranslator = hqlTranslator; + private static SqmFunctionRegistry createFunctionRegistry( + SessionFactoryImplementor sessionFactory, + MetadataImplementor metadata, + QueryEngineOptions queryEngineOptions, + Dialect dialect) { + final SqmFunctionRegistry sqmFunctionRegistry = new SqmFunctionRegistry(); - this.criteriaBuilder = new SqmCriteriaNodeBuilder( - uuid, - name, - jpaCompliance.isJpaQueryComplianceEnabled(), - this, - jpaMetamodelAccess, - serviceRegistry, - criteriaValueHandlingMode, - sessionFactory - ); + queryEngineOptions.getCustomSqlFunctionMap().forEach( sqmFunctionRegistry::register ); - this.sqmFunctionRegistry = new SqmFunctionRegistry(); - this.typeConfiguration = typeConfiguration; - this.preferredSqlTypeCodeForBoolean = preferredSqlTypeCodeForBoolean; - dialect.initializeFunctionRegistry( this ); - if ( userDefinedRegistry != null ) { - userDefinedRegistry.overlay( sqmFunctionRegistry ); + final SqmFunctionRegistry customSqmFunctionRegistry = queryEngineOptions.getCustomSqmFunctionRegistry(); + if ( customSqmFunctionRegistry != null ) { + customSqmFunctionRegistry.overlay( sqmFunctionRegistry ); } - final FunctionContributions functionContributions = new FunctionContributions() { - @Override - public TypeConfiguration getTypeConfiguration() { - return typeConfiguration; - } - - @Override - public SqmFunctionRegistry getFunctionRegistry() { - return sqmFunctionRegistry; - } - - @Override - public ServiceRegistry getServiceRegistry() { - return serviceRegistry; - } - }; - for ( FunctionContributor contributor : sortedFunctionContributors( serviceRegistry ) ) { + //TODO: probably better to turn this back into an anonymous class + final FunctionContributions functionContributions = new FunctionContributionsImpl( + sessionFactory.getServiceRegistry(), + metadata.getTypeConfiguration(), + sqmFunctionRegistry + ); + for ( FunctionContributor contributor : sortedFunctionContributors( sessionFactory.getServiceRegistry() ) ) { contributor.contributeFunctions( functionContributions ); } + // can't move this here just yet! + //dialect.initializeFunctionRegistry( this ); + if ( LOG_HQL_FUNCTIONS.isDebugEnabled() ) { sqmFunctionRegistry.getFunctionsByName().forEach( entry -> LOG_HQL_FUNCTIONS.debug( entry.getValue().getSignature( entry.getKey() ) ) ); } + + return sqmFunctionRegistry; + } + + private final NamedObjectRepository namedObjectRepository; + private final NativeQueryInterpreter nativeQueryInterpreter; + private final QueryInterpretationCache interpretationCache; + private final SqmCriteriaNodeBuilder criteriaBuilder; + private final HqlTranslator hqlTranslator; + private final SqmTranslatorFactory sqmTranslatorFactory; + private final SqmFunctionRegistry sqmFunctionRegistry; + private final TypeConfiguration typeConfiguration; + + private QueryEngine( + SessionFactoryImplementor sessionFactory, + TypeConfiguration typeConfiguration, + HqlTranslator hqlTranslator, + SqmTranslatorFactory sqmTranslatorFactory, + SqmFunctionRegistry functionRegistry, + NamedObjectRepository namedObjectRepository, + QueryInterpretationCache interpretationCache) { + this.typeConfiguration = typeConfiguration; + this.sqmFunctionRegistry = functionRegistry; + this.sqmTranslatorFactory = sqmTranslatorFactory; + this.hqlTranslator = hqlTranslator; + this.namedObjectRepository = namedObjectRepository; + this.interpretationCache = interpretationCache; + this.nativeQueryInterpreter = sessionFactory.getServiceRegistry().getService( NativeQueryInterpreter.class ); + final SessionFactoryOptions sessionFactoryOptions = sessionFactory.getSessionFactoryOptions(); + this.criteriaBuilder = new SqmCriteriaNodeBuilder( + sessionFactory.getUuid(), + sessionFactory.getName(), + this, + sessionFactoryOptions.getJpaCompliance().isJpaQueryComplianceEnabled(), + sessionFactoryOptions.getCriteriaValueHandlingMode(), + sessionFactory.getServiceRegistry(), + () -> sessionFactory + ); + // TODO: move into createFunctionRegistry() + sessionFactory.getJdbcServices().getDialect().initializeFunctionRegistry( this ); } /** @@ -227,62 +170,49 @@ public class QueryEngine implements QueryParameterBindingTypeResolver { this.namedObjectRepository = Objects.requireNonNull( namedObjectRepository ); this.sqmTranslatorFactory = null; this.nativeQueryInterpreter = Objects.requireNonNull( nativeQueryInterpreter ); - this.sqmFunctionRegistry = new SqmFunctionRegistry(); this.typeConfiguration = jpaMetamodel.getTypeConfiguration(); - this.preferredSqlTypeCodeForBoolean = preferredSqlTypeCodeForBoolean; dialect.initializeFunctionRegistry( this ); - SessionFactoryImplementor sessionFactory = jpaMetamodel.getTypeConfiguration().getSessionFactory(); - this.queryParameterBindingTypeResolver = sessionFactory; - this.criteriaBuilder = new SqmCriteriaNodeBuilder( - uuid, - name, - false, - this, - () -> jpaMetamodel, - serviceRegistry, - criteriaValueHandlingMode, - sessionFactory - ); - - final SqmCreationContext sqmCreationContext = new SqmCreationContext() { - @Override - public JpaMetamodelImplementor getJpaMetamodel() { - return jpaMetamodel; - } - - @Override - public ServiceRegistry getServiceRegistry() { - return serviceRegistry; - } - - @Override - public QueryEngine getQueryEngine() { - return QueryEngine.this; - } - - @Override - public NodeBuilder getNodeBuilder() { - return criteriaBuilder; - } - }; - - //noinspection Convert2Lambda - this.hqlTranslator = new StandardHqlTranslator( - sqmCreationContext, - new SqmCreationOptions() { - @Override - public boolean useStrictJpaCompliance() { - return useStrictJpaCompliance; - } - } - ); - this.interpretationCache = buildInterpretationCache( () -> serviceRegistry.getService( StatisticsImplementor.class ), serviceRegistry.getService( ConfigurationService.class ).getSettings() ); + + this.criteriaBuilder = new SqmCriteriaNodeBuilder( + uuid, + name, + this, + useStrictJpaCompliance, + criteriaValueHandlingMode, + serviceRegistry, + typeConfiguration::getSessionFactory + ); + + this.hqlTranslator = new StandardHqlTranslator( + new SqmCreationContext() { + @Override + public JpaMetamodelImplementor getJpaMetamodel() { + return jpaMetamodel; + } + + @Override + public ServiceRegistry getServiceRegistry() { + return serviceRegistry; + } + + @Override + public QueryEngine getQueryEngine() { + return QueryEngine.this; + } + + @Override + public NodeBuilder getNodeBuilder() { + return criteriaBuilder; + } + }, + () -> useStrictJpaCompliance + ); } private static HqlTranslator resolveHqlTranslator( @@ -413,17 +343,33 @@ public class QueryEngine implements QueryParameterBindingTypeResolver { } } - public int getPreferredSqlTypeCodeForBoolean() { - return preferredSqlTypeCodeForBoolean; - } + private static class FunctionContributionsImpl implements FunctionContributions { + private final ServiceRegistry serviceRegistry; + private final TypeConfiguration typeConfiguration; + private final SqmFunctionRegistry functionRegistry; - @Override - public BindableType resolveParameterBindType(T bindValue) { - return queryParameterBindingTypeResolver.resolveParameterBindType( bindValue ); - } + public FunctionContributionsImpl( + ServiceRegistry serviceRegistry, + TypeConfiguration typeConfiguration, + SqmFunctionRegistry functionRegistry) { + this.serviceRegistry = serviceRegistry; + this.typeConfiguration = typeConfiguration; + this.functionRegistry = functionRegistry; + } - @Override - public BindableType resolveParameterBindType(Class clazz) { - return queryParameterBindingTypeResolver.resolveParameterBindType( clazz ); + @Override + public TypeConfiguration getTypeConfiguration() { + return typeConfiguration; + } + + @Override + public SqmFunctionRegistry getFunctionRegistry() { + return functionRegistry; + } + + @Override + public ServiceRegistry getServiceRegistry() { + return serviceRegistry; + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/QueryEngineOptions.java b/hibernate-core/src/main/java/org/hibernate/query/spi/QueryEngineOptions.java index 5df5238497..eae97d9fc6 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/spi/QueryEngineOptions.java +++ b/hibernate-core/src/main/java/org/hibernate/query/spi/QueryEngineOptions.java @@ -9,6 +9,7 @@ package org.hibernate.query.spi; import java.util.Map; import org.hibernate.jpa.spi.JpaCompliance; +import org.hibernate.query.criteria.ValueHandlingMode; import org.hibernate.query.hql.HqlTranslator; import org.hibernate.query.sqm.function.SqmFunctionDescriptor; import org.hibernate.query.sqm.function.SqmFunctionRegistry; @@ -69,4 +70,6 @@ public interface QueryEngineOptions { SqmMultiTableInsertStrategy getCustomSqmMultiTableInsertStrategy(); JpaCompliance getJpaCompliance(); + + ValueHandlingMode getCriteriaValueHandlingMode(); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/QueryParameterBindingTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/query/spi/QueryParameterBindingTypeResolver.java index 6f98cbae16..6b2ea0b8a5 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/spi/QueryParameterBindingTypeResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/query/spi/QueryParameterBindingTypeResolver.java @@ -6,12 +6,17 @@ */ package org.hibernate.query.spi; +import org.hibernate.metamodel.MappingMetamodel; import org.hibernate.query.BindableType; import org.hibernate.type.spi.TypeConfiguration; /** - * A resolver for Type based on a parameter value being bound, when no - * explicit type information is supplied. + * A resolver for {@link BindableType} based on a parameter value being bound, when no explicit type information is + * supplied. + * + * @apiNote This interface was originally a supertype of {@link org.hibernate.engine.spi.SessionFactoryImplementor}, + * but this is now a deprecated relationship. Its functionality should now be accessed via its new subtype + * {@link org.hibernate.metamodel.spi.MappingMetamodelImplementor}. * * @author Steve Ebersole */ @@ -19,4 +24,5 @@ public interface QueryParameterBindingTypeResolver { BindableType resolveParameterBindType(T bindValue); BindableType resolveParameterBindType(Class clazz); TypeConfiguration getTypeConfiguration(); + MappingMetamodel getMappingMetamodel(); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java index 4b22efbd36..c52a93283a 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java @@ -43,6 +43,7 @@ import org.hibernate.metamodel.model.domain.BasicDomainType; import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; +import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.query.BindableType; import org.hibernate.query.ReturnableType; import org.hibernate.query.SemanticException; @@ -180,35 +181,31 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, private final String name; private final transient boolean jpaComplianceEnabled; private final transient QueryEngine queryEngine; - private final transient Supplier domainModelAccess; private final transient ServiceRegistry serviceRegistry; + private final transient Supplier sessionFactory; private final transient ValueHandlingMode criteriaValueHandlingMode; - private final transient SessionFactoryImplementor sessionFactory; private transient BasicType booleanType; private transient BasicType integerType; private transient BasicType characterType; private final transient Map, HibernateCriteriaBuilder> extensions; public SqmCriteriaNodeBuilder( - String uuid, - String name, - boolean jpaComplianceEnabled, + String uuid, String name, QueryEngine queryEngine, - Supplier domainModelAccess, - ServiceRegistry serviceRegistry, + boolean jpaComplianceEnabled, ValueHandlingMode criteriaValueHandlingMode, - SessionFactoryImplementor sessionFactory) { + ServiceRegistry serviceRegistry, + Supplier sessionFactory) { + this.serviceRegistry = serviceRegistry; this.sessionFactory = sessionFactory; + this.queryEngine = queryEngine; this.uuid = uuid; this.name = name; this.jpaComplianceEnabled = jpaComplianceEnabled; - this.queryEngine = queryEngine; - this.domainModelAccess = domainModelAccess; - this.serviceRegistry = serviceRegistry; this.criteriaValueHandlingMode = criteriaValueHandlingMode; // load registered criteria builder extensions this.extensions = new HashMap<>(); - for (CriteriaBuilderExtension extension : ServiceLoader.load( CriteriaBuilderExtension.class ) ) { + for ( CriteriaBuilderExtension extension : ServiceLoader.load( CriteriaBuilderExtension.class ) ) { HibernateCriteriaBuilder builder = extension.extend( this ); extensions.put( extension.getRegistrationKey(), builder ); } @@ -216,7 +213,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, @Override public JpaMetamodel getDomainModel() { - return domainModelAccess.get(); + return getSessionFactory().getJpaMetamodel(); } @Override @@ -231,7 +228,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, @Override public SessionFactoryImplementor getSessionFactory() { - return sessionFactory; + return sessionFactory.get(); } @Override @@ -274,7 +271,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, @Override public JpaMetamodelImplementor getJpaMetamodel() { - return domainModelAccess.get(); + return getSessionFactory().getJpaMetamodel(); } public void close() { @@ -621,7 +618,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, expressibleType = (DomainType) typeConfiguration.resolveTupleType( sqmExpressions ); } else { - expressibleType = domainModelAccess.get().embeddable( tupleType ); + expressibleType = getDomainModel().embeddable( tupleType ); } return tuple( expressibleType, sqmExpressions ); } @@ -1192,14 +1189,18 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, return new SqmLiteralNull<>( this ); } - final BindableType valueParamType = queryEngine.resolveParameterBindType( value ); + final BindableType valueParamType = getMappingMetamodel().resolveParameterBindType( value ); final SqmExpressible sqmExpressible = valueParamType == null ? null - : valueParamType.resolveExpressible( sessionFactory ); + : valueParamType.resolveExpressible( getSessionFactory() ); return new SqmLiteral<>( value, sqmExpressible, this ); } + private MappingMetamodelImplementor getMappingMetamodel() { + return getSessionFactory().getMappingMetamodel(); + } + @Override public List> literals(T[] values) { if ( values == null || values.length == 0 ) { @@ -1231,7 +1232,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, final TypeConfiguration typeConfiguration = getTypeConfiguration(); final BasicType basicTypeForJavaType = typeConfiguration.getBasicTypeForJavaType( resultClass ); final SqmExpressible sqmExpressible = basicTypeForJavaType == null - ? domainModelAccess.get().managedType( resultClass ) + ? getDomainModel().managedType( resultClass ) : basicTypeForJavaType; return new SqmLiteralNull<>(sqmExpressible, this ); } @@ -1240,10 +1241,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, private final JavaType javaType; public MultiValueParameterType(Class type) { - this.javaType = domainModelAccess.get() - .getTypeConfiguration() - .getJavaTypeRegistry() - .getDescriptor( type ); + this.javaType = getTypeConfiguration().getJavaTypeRegistry().getDescriptor( type ); } @Override @@ -1723,7 +1721,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, this ); } - final SqmExpressible expressible = bindableType.resolveExpressible( sessionFactory ); + final SqmExpressible expressible = bindableType.resolveExpressible( getSessionFactory() ); T coercedValue = expressible.getExpressibleJavaType().coerce( value, this::getTypeConfiguration ); if ( isInstance( bindableType, coercedValue ) ) { return new ValueBindJpaCriteriaParameter<>( @@ -1735,7 +1733,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, else { // ignore typeInferenceSource and fallback the value type return new ValueBindJpaCriteriaParameter<>( - queryEngine.resolveParameterBindType( value ), + getMappingMetamodel().resolveParameterBindType( value ), value, this ); @@ -1749,7 +1747,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, if ( bindableType.getBindableJavaType().isInstance( value ) ) { return true; } - return bindableType.resolveExpressible( sessionFactory ) + return bindableType.resolveExpressible( getSessionFactory() ) .getExpressibleJavaType() .isInstance( value ); } @@ -1788,7 +1786,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, } else { return new ValueBindJpaCriteriaParameter<>( - queryEngine.resolveParameterBindType( value ), + getMappingMetamodel().resolveParameterBindType( value ), value, this ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/AbstractJdbcParameter.java b/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/AbstractJdbcParameter.java index 014db851da..08f84bbb3c 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/AbstractJdbcParameter.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/AbstractJdbcParameter.java @@ -118,9 +118,9 @@ public abstract class AbstractJdbcParameter return jdbcMapping; } - final BindableType parameterType = executionContext.getSession() - .getFactory() - .resolveParameterBindType( bindValue ); + final BindableType parameterType = + executionContext.getSession().getFactory().getMappingMetamodel() + .resolveParameterBindType( bindValue ); if ( parameterType instanceof JdbcMapping ) { return (JdbcMapping) parameterType; }