From 9f91f2dbff6279f7ac04cc39ad0a8cdfeeae5e90 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Mon, 9 Sep 2024 22:59:16 +0200 Subject: [PATCH] major refactor to horrible instantiation of QueryEngine --- .../InFlightMetadataCollectorImpl.java | 2 +- .../hibernate/boot/internal/MetadataImpl.java | 11 +-- .../boot/spi/AbstractDelegatingMetadata.java | 4 +- .../boot/spi/MetadataImplementor.java | 2 +- .../boot/spi/SessionFactoryOptions.java | 5 -- .../internal/SessionFactoryImpl.java | 4 +- .../org/hibernate/query/BindableType.java | 5 +- .../org/hibernate/query/BindingContext.java | 27 ++++++ .../query/internal/BindingTypeHelper.java | 8 +- .../query/internal/QueryEngineImpl.java | 83 +++++++++--------- .../QueryInterpretationCacheDisabledImpl.java | 20 +++-- .../QueryInterpretationCacheStandardImpl.java | 20 +++-- .../query/spi/QueryEngineOptions.java | 8 ++ .../spi/QueryParameterBindingValidator.java | 10 +-- .../org/hibernate/query/sqm/NodeBuilder.java | 10 ++- .../hibernate/query/sqm/SqmExpressible.java | 4 +- .../sqm/internal/SqmCriteriaNodeBuilder.java | 57 +++++++------ .../hibernate/query/sqm/internal/SqmUtil.java | 43 +++++----- .../query/sqm/internal/TypecheckUtil.java | 85 +++++++++---------- .../query/sqm/spi/SqmCreationContext.java | 3 +- .../sqm/sql/BaseSqmToSqlAstConverter.java | 2 +- .../sqm/tree/domain/AbstractSqmPath.java | 2 +- .../tree/expression/JpaCriteriaParameter.java | 2 +- .../tree/expression/SqmExpressionHelper.java | 18 ++-- .../insert/AbstractSqmInsertStatement.java | 4 +- .../tree/insert/SqmConflictUpdateAction.java | 2 +- .../tree/predicate/SqmBetweenPredicate.java | 4 +- .../predicate/SqmComparisonPredicate.java | 4 +- .../tree/predicate/SqmInListPredicate.java | 2 +- .../predicate/SqmInSubQueryPredicate.java | 2 +- .../tree/predicate/SqmMemberOfPredicate.java | 2 +- .../sqm/tree/update/SqmUpdateStatement.java | 13 +-- .../sql/ast/spi/SqlAstCreationContext.java | 3 +- .../hibernate/type/BasicTypeReference.java | 6 +- .../org/hibernate/type/ComponentType.java | 5 +- .../orm/test/query/sqm/BaseSqmUnitTest.java | 12 +++ .../orm/test/type/contributor/ArrayType.java | 4 +- .../validation/MockSessionFactory.java | 16 ++-- 38 files changed, 287 insertions(+), 227 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/query/BindingContext.java diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java index 18fcf2fdcf..9cba36ed20 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java @@ -287,7 +287,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector, } @Override - public NamedObjectRepository buildNamedQueryRepository(SessionFactoryImplementor sessionFactory) { + public NamedObjectRepository buildNamedQueryRepository() { throw new UnsupportedOperationException( "#buildNamedQueryRepository should not be called on InFlightMetadataCollector" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java index 6cf3db19cb..8387f7bc31 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java @@ -71,6 +71,7 @@ import org.hibernate.type.spi.TypeConfiguration; import static org.hibernate.cfg.AvailableSettings.EVENT_LISTENER_PREFIX; import static org.hibernate.internal.util.StringHelper.splitAtCommas; +import static org.hibernate.internal.util.collections.CollectionHelper.mapOfSize; /** * Container for configuration data collected during binding the metamodel. @@ -356,12 +357,12 @@ public class MetadataImpl implements MetadataImplementor, Serializable { } @Override - public NamedObjectRepository buildNamedQueryRepository(SessionFactoryImplementor sessionFactory) { + public NamedObjectRepository buildNamedQueryRepository() { return new NamedObjectRepositoryImpl( - CollectionHelper.mapOfSize( namedQueryMap.size() ), - CollectionHelper.mapOfSize( namedNativeQueryMap.size() ), - CollectionHelper.mapOfSize( namedProcedureCallMap.size() ), - CollectionHelper.mapOfSize( sqlResultSetMappingMap.size() ) + mapOfSize( namedQueryMap.size() ), + mapOfSize( namedNativeQueryMap.size() ), + mapOfSize( namedProcedureCallMap.size() ), + mapOfSize( sqlResultSetMappingMap.size() ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingMetadata.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingMetadata.java index 788fc2338a..6b077ecc7c 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingMetadata.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingMetadata.java @@ -259,8 +259,8 @@ public abstract class AbstractDelegatingMetadata implements MetadataImplementor } @Override - public NamedObjectRepository buildNamedQueryRepository(SessionFactoryImplementor sessionFactory) { - return delegate().buildNamedQueryRepository( sessionFactory ); + public NamedObjectRepository buildNamedQueryRepository() { + return delegate().buildNamedQueryRepository(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataImplementor.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataImplementor.java index b41e28ce03..30d25daa4d 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataImplementor.java @@ -46,7 +46,7 @@ public interface MetadataImplementor extends Metadata { */ SqmFunctionRegistry getFunctionRegistry(); - NamedObjectRepository buildNamedQueryRepository(SessionFactoryImplementor sessionFactory); + NamedObjectRepository buildNamedQueryRepository(); @Incubating void orderColumns(boolean forceOrdering); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java index 80bd254667..2a60d78149 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java @@ -25,7 +25,6 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.BaselineSessionEventsListenerBuilder; import org.hibernate.jpa.spi.JpaCompliance; import org.hibernate.proxy.EntityNotFoundDelegate; -import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode; import org.hibernate.query.criteria.ValueHandlingMode; import org.hibernate.query.spi.QueryEngineOptions; import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode; @@ -242,10 +241,6 @@ public interface SessionFactoryOptions extends QueryEngineOptions { boolean isFailOnPaginationOverCollectionFetchEnabled(); - default ImmutableEntityUpdateQueryHandlingMode getImmutableEntityUpdateQueryHandlingMode() { - return ImmutableEntityUpdateQueryHandlingMode.WARNING; - } - /** * The default catalog to use in generated SQL when a catalog wasn't specified in the mapping, * neither explicitly nor implicitly (see the concept of implicit catalog in XML mapping). 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 949f8db7fd..7d2ffe7b2e 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -227,7 +227,7 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im settings = getSettings( options, serviceRegistry ); maskOutSensitiveInformation( settings ); deprecationCheck( settings ); - LOG.debugf( "Instantiating SessionFactory with settings: %s", settings); + LOG.debugf( "Instantiating SessionFactory with settings: %s", settings ); sqlStringGenerationContext = createSqlStringGenerationContext( bootMetamodel, options, jdbcServices ); @@ -280,7 +280,7 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im // created, then we can split creation of QueryEngine // and SqmFunctionRegistry, instantiating just the // registry here, and doing the engine later - queryEngine = QueryEngineImpl.from( this, bootMetamodel ); + queryEngine = QueryEngineImpl.from( bootMetamodel, options, this, serviceRegistry, settings, name ); // create runtime metamodels (mapping and JPA) final RuntimeMetamodelsImpl runtimeMetamodelsImpl = new RuntimeMetamodelsImpl(); diff --git a/hibernate-core/src/main/java/org/hibernate/query/BindableType.java b/hibernate-core/src/main/java/org/hibernate/query/BindableType.java index 3d5a241dc1..59a494150f 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/BindableType.java +++ b/hibernate-core/src/main/java/org/hibernate/query/BindableType.java @@ -7,7 +7,6 @@ package org.hibernate.query; import org.hibernate.Incubating; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.query.sqm.SqmExpressible; /** @@ -30,7 +29,7 @@ public interface BindableType { } /** - * Resolve this parameter type to the corresponding SqmExpressible + * Resolve this parameter type to the corresponding {@link SqmExpressible} */ - SqmExpressible resolveExpressible(SessionFactoryImplementor sessionFactory); + SqmExpressible resolveExpressible(BindingContext bindingContext); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/BindingContext.java b/hibernate-core/src/main/java/org/hibernate/query/BindingContext.java new file mode 100644 index 0000000000..56be2540b9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/query/BindingContext.java @@ -0,0 +1,27 @@ +/* + * 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 http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.query; + +import org.hibernate.Incubating; +import org.hibernate.metamodel.MappingMetamodel; +import org.hibernate.metamodel.model.domain.JpaMetamodel; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * A context within which a {@link BindableType} can be resolved + * to an instance of {@link org.hibernate.query.sqm.SqmExpressible}. + * + * @author Gavin King + * + * @since 7 + */ +@Incubating +public interface BindingContext { + TypeConfiguration getTypeConfiguration(); + JpaMetamodel getJpaMetamodel(); + MappingMetamodel getMappingMetamodel(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/BindingTypeHelper.java b/hibernate-core/src/main/java/org/hibernate/query/internal/BindingTypeHelper.java index 2fe6aa6978..bb74715534 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/BindingTypeHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/BindingTypeHelper.java @@ -13,9 +13,9 @@ import java.time.OffsetTime; import java.time.ZonedDateTime; import java.util.Calendar; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.query.BindableType; +import org.hibernate.query.BindingContext; import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.java.JavaTypeHelper; @@ -39,9 +39,9 @@ public class BindingTypeHelper { public BindableType resolveTemporalPrecision( TemporalType precision, BindableType declaredParameterType, - SessionFactoryImplementor sessionFactory) { + BindingContext bindingContext) { if ( precision != null ) { - final SqmExpressible sqmExpressible = declaredParameterType.resolveExpressible( sessionFactory ); + final SqmExpressible sqmExpressible = declaredParameterType.resolveExpressible(bindingContext); if ( !( JavaTypeHelper.isTemporal( sqmExpressible.getExpressibleJavaType() ) ) ) { throw new UnsupportedOperationException( "Cannot treat non-temporal parameter type with temporal precision" @@ -50,7 +50,7 @@ public class BindingTypeHelper { final TemporalJavaType temporalJtd = (TemporalJavaType) sqmExpressible.getExpressibleJavaType(); if ( temporalJtd.getPrecision() != precision ) { - final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration(); + final TypeConfiguration typeConfiguration = bindingContext.getTypeConfiguration(); final TemporalJavaType temporalTypeForPrecision; // Special case java.util.Date, because TemporalJavaType#resolveTypeForPrecision doesn't support widening, // since the main purpose of that method is to determine the final java type based on the reflective type diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryEngineImpl.java b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryEngineImpl.java index 9ff6c595a6..d3988b9131 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryEngineImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryEngineImpl.java @@ -10,13 +10,13 @@ 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.jdbc.spi.JdbcServices; 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.query.BindingContext; import org.hibernate.query.hql.HqlTranslator; import org.hibernate.query.hql.internal.StandardHqlTranslator; import org.hibernate.query.hql.spi.SqmCreationOptions; @@ -32,7 +32,7 @@ import org.hibernate.query.sqm.spi.SqmCreationContext; import org.hibernate.query.sqm.sql.SqmTranslatorFactory; import org.hibernate.query.sqm.sql.StandardSqmTranslatorFactory; import org.hibernate.service.ServiceRegistry; -import org.hibernate.stat.spi.StatisticsImplementor; +import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.type.spi.TypeConfiguration; import org.jboss.logging.Logger; @@ -40,7 +40,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.function.Supplier; import static java.util.Comparator.comparingInt; @@ -54,23 +53,31 @@ public class QueryEngineImpl implements QueryEngine { private static final Logger LOG_HQL_FUNCTIONS = CoreLogging.logger("org.hibernate.HQL_FUNCTIONS"); - public static QueryEngine from(SessionFactoryImplementor sessionFactory, MetadataImplementor metadata) { - final QueryEngineOptions options = sessionFactory.getSessionFactoryOptions(); - final Dialect dialect = sessionFactory.getJdbcServices().getDialect(); + public static QueryEngineImpl from( + MetadataImplementor metadata, + QueryEngineOptions options, + SqmCreationContext sqmCreationContext, + ServiceRegistryImplementor serviceRegistry, + Map properties, + String name) { + final Dialect dialect = serviceRegistry.requireService( JdbcServices.class ).getDialect(); return new QueryEngineImpl( - sessionFactory, metadata.getTypeConfiguration(), - resolveHqlTranslator( options, dialect, sessionFactory, new SqmCreationOptionsStandard( options ) ), + resolveHqlTranslator( options, dialect, sqmCreationContext, new SqmCreationOptionsStandard( options ) ), resolveSqmTranslatorFactory( options, dialect ), - createFunctionRegistry( sessionFactory, metadata, options, dialect ), - metadata.buildNamedQueryRepository( sessionFactory ), - buildInterpretationCache( sessionFactory::getStatistics, sessionFactory.getProperties() ), - sessionFactory.getServiceRegistry().getService(NativeQueryInterpreter.class) + createFunctionRegistry( serviceRegistry, metadata, options, dialect ), + metadata.buildNamedQueryRepository(), + buildInterpretationCache( serviceRegistry, properties ), + serviceRegistry.getService(NativeQueryInterpreter.class), + sqmCreationContext, + options, + options.getUuid(), + name ); } private static SqmFunctionRegistry createFunctionRegistry( - SessionFactoryImplementor sessionFactory, + ServiceRegistry serviceRegistry, MetadataImplementor metadata, QueryEngineOptions queryEngineOptions, Dialect dialect) { @@ -84,21 +91,17 @@ public class QueryEngineImpl implements QueryEngine { } //TODO: probably better to turn this back into an anonymous class - final FunctionContributions functionContributions = new QueryEngineImpl.FunctionContributionsImpl( - sessionFactory.getServiceRegistry(), - metadata.getTypeConfiguration(), - sqmFunctionRegistry - ); - for ( FunctionContributor contributor : sortedFunctionContributors( sessionFactory.getServiceRegistry() ) ) { + final FunctionContributions functionContributions = + new FunctionContributionsImpl( serviceRegistry, metadata.getTypeConfiguration(), sqmFunctionRegistry ); + for ( FunctionContributor contributor : sortedFunctionContributors( serviceRegistry ) ) { contributor.contributeFunctions( functionContributions ); } dialect.initializeFunctionRegistry( functionContributions ); if ( LOG_HQL_FUNCTIONS.isDebugEnabled() ) { - sqmFunctionRegistry.getFunctionsByName().forEach( - entry -> LOG_HQL_FUNCTIONS.debug( entry.getValue().getSignature( entry.getKey() ) ) - ); + sqmFunctionRegistry.getFunctionsByName() + .forEach( entry -> LOG_HQL_FUNCTIONS.debug( entry.getValue().getSignature( entry.getKey() ) ) ); } return sqmFunctionRegistry; @@ -114,14 +117,16 @@ public class QueryEngineImpl implements QueryEngine { private final SqmFunctionRegistry sqmFunctionRegistry; private QueryEngineImpl( - SessionFactoryImplementor sessionFactory, TypeConfiguration typeConfiguration, HqlTranslator hqlTranslator, SqmTranslatorFactory sqmTranslatorFactory, SqmFunctionRegistry functionRegistry, NamedObjectRepository namedObjectRepository, QueryInterpretationCache interpretationCache, - NativeQueryInterpreter nativeQueryInterpreter) { + NativeQueryInterpreter nativeQueryInterpreter, + BindingContext context, + QueryEngineOptions options, + String uuid, String name) { this.typeConfiguration = typeConfiguration; this.sqmFunctionRegistry = functionRegistry; this.sqmTranslatorFactory = sqmTranslatorFactory; @@ -129,15 +134,13 @@ public class QueryEngineImpl implements QueryEngine { this.namedObjectRepository = namedObjectRepository; this.interpretationCache = interpretationCache; this.nativeQueryInterpreter = nativeQueryInterpreter; - final SessionFactoryOptions sessionFactoryOptions = sessionFactory.getSessionFactoryOptions(); - this.criteriaBuilder = new SqmCriteriaNodeBuilder( - sessionFactory.getUuid(), - sessionFactory.getName(), - this, - sessionFactoryOptions.getJpaCompliance().isJpaQueryComplianceEnabled(), - sessionFactoryOptions.getCriteriaValueHandlingMode(), - () -> sessionFactory - ); + this.criteriaBuilder = createCriteriaBuilder( context, options, uuid, name ); + } + + private SqmCriteriaNodeBuilder createCriteriaBuilder( + BindingContext context, QueryEngineOptions options, + String uuid, String name) { + return new SqmCriteriaNodeBuilder( uuid, name, this, options, context ); } private static HqlTranslator resolveHqlTranslator( @@ -171,10 +174,10 @@ public class QueryEngineImpl implements QueryEngine { } private static List sortedFunctionContributors(ServiceRegistry serviceRegistry) { - Collection functionContributors = + final Collection functionContributors = serviceRegistry.requireService(ClassLoaderService.class) .loadJavaServices(FunctionContributor.class); - List contributors = new ArrayList<>( functionContributors ); + final List contributors = new ArrayList<>( functionContributors ); contributors.sort( comparingInt( FunctionContributor::ordinal ) .thenComparing( a -> a.getClass().getCanonicalName() ) @@ -183,8 +186,7 @@ public class QueryEngineImpl implements QueryEngine { } private static QueryInterpretationCache buildInterpretationCache( - Supplier statisticsSupplier, - Map properties) { + ServiceRegistry serviceRegistry, Map properties) { final boolean explicitUseCache = ConfigurationHelper.getBoolean( AvailableSettings.QUERY_PLAN_CACHE_ENABLED, properties, @@ -202,11 +204,11 @@ public class QueryEngineImpl implements QueryEngine { ? explicitMaxPlanSize : QueryEngine.DEFAULT_QUERY_PLAN_MAX_COUNT; - return new QueryInterpretationCacheStandardImpl( size, statisticsSupplier ); + return new QueryInterpretationCacheStandardImpl( size, serviceRegistry ); } else { // disabled - return new QueryInterpretationCacheDisabledImpl( statisticsSupplier ); + return new QueryInterpretationCacheDisabledImpl( serviceRegistry ); } } @@ -299,5 +301,4 @@ public class QueryEngineImpl implements QueryEngine { return serviceRegistry; } } - } diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryInterpretationCacheDisabledImpl.java b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryInterpretationCacheDisabledImpl.java index f2ac2c04af..eceb715723 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryInterpretationCacheDisabledImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryInterpretationCacheDisabledImpl.java @@ -20,6 +20,7 @@ import org.hibernate.query.sql.spi.ParameterInterpretation; import org.hibernate.query.sqm.internal.DomainParameterXref; import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.select.SqmSelectStatement; +import org.hibernate.service.ServiceRegistry; import org.hibernate.stat.spi.StatisticsImplementor; /** @@ -27,10 +28,12 @@ import org.hibernate.stat.spi.StatisticsImplementor; */ public class QueryInterpretationCacheDisabledImpl implements QueryInterpretationCache { - private final Supplier statisticsSupplier; + private final ServiceRegistry serviceRegistry; - public QueryInterpretationCacheDisabledImpl(Supplier statisticsSupplier) { - this.statisticsSupplier = statisticsSupplier; + private StatisticsImplementor statistics; + + public QueryInterpretationCacheDisabledImpl(ServiceRegistry serviceRegistry) { + this.serviceRegistry = serviceRegistry; } @Override @@ -43,9 +46,16 @@ public class QueryInterpretationCacheDisabledImpl implements QueryInterpretation return 0; } + private StatisticsImplementor getStatistics() { + if ( statistics == null ) { + statistics = serviceRegistry.requireService( StatisticsImplementor.class ); + } + return statistics; + } + @Override public SelectQueryPlan resolveSelectQueryPlan(Key key, Supplier> creator) { - final StatisticsImplementor statistics = statisticsSupplier.get(); + final StatisticsImplementor statistics = getStatistics(); if ( statistics.isStatisticsEnabled() ) { statistics.queryPlanCacheMiss( key.getQueryString() ); } @@ -64,7 +74,7 @@ public class QueryInterpretationCacheDisabledImpl implements QueryInterpretation @Override public HqlInterpretation resolveHqlInterpretation( String queryString, Class expectedResultType, HqlTranslator translator) { - final StatisticsImplementor statistics = statisticsSupplier.get(); + final StatisticsImplementor statistics = getStatistics(); final boolean stats = statistics.isStatisticsEnabled(); final long startTime = stats ? System.nanoTime() : 0L; diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryInterpretationCacheStandardImpl.java b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryInterpretationCacheStandardImpl.java index e954097ff7..9c3e036c4d 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryInterpretationCacheStandardImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryInterpretationCacheStandardImpl.java @@ -23,6 +23,7 @@ import org.hibernate.query.spi.SimpleHqlInterpretationImpl; import org.hibernate.query.sql.spi.ParameterInterpretation; import org.hibernate.query.sqm.internal.DomainParameterXref; import org.hibernate.query.sqm.tree.SqmStatement; +import org.hibernate.service.ServiceRegistry; import org.hibernate.stat.spi.StatisticsImplementor; import org.jboss.logging.Logger; @@ -40,17 +41,19 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation */ private final BoundedConcurrentHashMap queryPlanCache; + private final ServiceRegistry serviceRegistry; private final BoundedConcurrentHashMap> hqlInterpretationCache; private final BoundedConcurrentHashMap nativeQueryParamCache; - private final Supplier statisticsSupplier; - public QueryInterpretationCacheStandardImpl(int maxQueryPlanCount, Supplier statisticsSupplier) { + private StatisticsImplementor statistics; + + public QueryInterpretationCacheStandardImpl(int maxQueryPlanCount, ServiceRegistry serviceRegistry) { log.debugf( "Starting QueryInterpretationCache(%s)", maxQueryPlanCount ); this.queryPlanCache = new BoundedConcurrentHashMap<>( maxQueryPlanCount, 20, BoundedConcurrentHashMap.Eviction.LIRS ); this.hqlInterpretationCache = new BoundedConcurrentHashMap<>( maxQueryPlanCount, 20, BoundedConcurrentHashMap.Eviction.LIRS ); this.nativeQueryParamCache = new BoundedConcurrentHashMap<>( maxQueryPlanCount, 20, BoundedConcurrentHashMap.Eviction.LIRS ); - this.statisticsSupplier = statisticsSupplier; + this.serviceRegistry = serviceRegistry; } @Override @@ -63,12 +66,19 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation return queryPlanCache.size(); } + private StatisticsImplementor getStatistics() { + if ( statistics == null ) { + statistics = serviceRegistry.requireService( StatisticsImplementor.class ); + } + return statistics; + } + @Override public SelectQueryPlan resolveSelectQueryPlan( Key key, Supplier> creator) { log.tracef( "QueryPlan#getSelectQueryPlan(%s)", key ); - final StatisticsImplementor statistics = statisticsSupplier.get(); + final StatisticsImplementor statistics = getStatistics(); final boolean stats = statistics.isStatisticsEnabled(); @SuppressWarnings("unchecked") @@ -105,7 +115,7 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation Class expectedResultType, HqlTranslator translator) { log.tracef( "QueryPlan#resolveHqlInterpretation( `%s` )", queryString ); - final StatisticsImplementor statistics = statisticsSupplier.get(); + final StatisticsImplementor statistics = getStatistics(); final Object cacheKey = expectedResultType != null ? new HqlInterpretationCacheKey( queryString, expectedResultType ) 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 8a4dbb2e22..bbfbf4ea6e 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.ImmutableEntityUpdateQueryHandlingMode; import org.hibernate.query.criteria.ValueHandlingMode; import org.hibernate.query.hql.HqlTranslator; import org.hibernate.query.sqm.function.SqmFunctionDescriptor; @@ -73,9 +74,16 @@ public interface QueryEngineOptions { ValueHandlingMode getCriteriaValueHandlingMode(); + default ImmutableEntityUpdateQueryHandlingMode getImmutableEntityUpdateQueryHandlingMode() { + return ImmutableEntityUpdateQueryHandlingMode.WARNING; + } + /** * @see org.hibernate.cfg.AvailableSettings#PORTABLE_INTEGER_DIVISION */ boolean isPortableIntegerDivisionEnabled(); + String getSessionFactoryName(); + + String getUuid(); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/QueryParameterBindingValidator.java b/hibernate-core/src/main/java/org/hibernate/query/spi/QueryParameterBindingValidator.java index d2676b278e..1cc880ad36 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/spi/QueryParameterBindingValidator.java +++ b/hibernate-core/src/main/java/org/hibernate/query/spi/QueryParameterBindingValidator.java @@ -10,9 +10,9 @@ import java.util.Calendar; import java.util.Collection; import java.util.Date; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.query.BindableType; import org.hibernate.query.QueryArgumentException; +import org.hibernate.query.BindingContext; import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.type.descriptor.java.JavaType; @@ -28,22 +28,22 @@ public class QueryParameterBindingValidator { private QueryParameterBindingValidator() { } - public void validate(BindableType paramType, Object bind, SessionFactoryImplementor sessionFactory) { - validate( paramType, bind, null, sessionFactory ); + public void validate(BindableType paramType, Object bind, BindingContext bindingContext) { + validate( paramType, bind, null, bindingContext); } public void validate( BindableType paramType, Object bind, TemporalType temporalPrecision, - SessionFactoryImplementor sessionFactory) { + BindingContext bindingContext) { if ( bind == null || paramType == null ) { // nothing we can check return; } final Class parameterJavaType; - final SqmExpressible sqmExpressible = paramType.resolveExpressible( sessionFactory ); + final SqmExpressible sqmExpressible = paramType.resolveExpressible(bindingContext); if ( paramType.getBindableJavaType() != null ) { parameterJavaType = paramType.getBindableJavaType(); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/NodeBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/NodeBuilder.java index ed28fa0a31..83dcf96ad0 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/NodeBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/NodeBuilder.java @@ -17,9 +17,11 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.jpa.spi.JpaCompliance; import org.hibernate.metamodel.model.domain.JpaMetamodel; +import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode; import org.hibernate.query.NullPrecedence; +import org.hibernate.query.BindingContext; import org.hibernate.query.SortDirection; import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.query.criteria.JpaCoalesce; @@ -78,7 +80,7 @@ import jakarta.persistence.criteria.Subquery; * @author Steve Ebersole */ @SuppressWarnings("unchecked") -public interface NodeBuilder extends HibernateCriteriaBuilder { +public interface NodeBuilder extends HibernateCriteriaBuilder, BindingContext { JpaMetamodel getDomainModel(); TypeConfiguration getTypeConfiguration(); @@ -1194,5 +1196,7 @@ public interface NodeBuilder extends HibernateCriteriaBuilder { BasicType getCharacterType(); - SessionFactoryImplementor getSessionFactory(); + JpaCompliance getJpaCompliance(); + + ImmutableEntityUpdateQueryHandlingMode getImmutableEntityUpdateQueryHandlingMode(); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmExpressible.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmExpressible.java index 31df20d6e3..68290fdf18 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmExpressible.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmExpressible.java @@ -6,9 +6,9 @@ */ package org.hibernate.query.sqm; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.query.BindableType; +import org.hibernate.query.BindingContext; import org.hibernate.query.sqm.tree.expression.SqmExpression; import org.hibernate.type.descriptor.java.JavaType; @@ -36,7 +36,7 @@ public interface SqmExpressible extends BindableType { } @Override - default SqmExpressible resolveExpressible(SessionFactoryImplementor sessionFactory) { + default SqmExpressible resolveExpressible(BindingContext bindingContext) { return this; } 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 0ec7285cce..c6ea2d4f60 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 @@ -7,6 +7,7 @@ package org.hibernate.query.sqm.internal; import java.io.InvalidObjectException; +import java.io.Serial; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; @@ -31,18 +32,17 @@ import java.util.List; import java.util.Map; import java.util.ServiceLoader; import java.util.Set; -import java.util.function.Supplier; import org.hibernate.SessionFactory; import org.hibernate.dialect.function.AvgFunction; import org.hibernate.dialect.function.SumReturnTypeResolver; import org.hibernate.dialect.function.array.DdlTypeHelper; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.SessionFactoryRegistry; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jpa.spi.JpaCompliance; import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; @@ -50,7 +50,9 @@ import org.hibernate.metamodel.model.domain.internal.BasicTypeImpl; import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.query.BindableType; +import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode; import org.hibernate.query.NullPrecedence; +import org.hibernate.query.BindingContext; import org.hibernate.query.ReturnableType; import org.hibernate.query.SemanticException; import org.hibernate.query.SortDirection; @@ -72,6 +74,7 @@ import org.hibernate.query.criteria.JpaWindow; import org.hibernate.query.criteria.ValueHandlingMode; import org.hibernate.query.criteria.spi.CriteriaBuilderExtension; import org.hibernate.query.spi.QueryEngine; +import org.hibernate.query.spi.QueryEngineOptions; import org.hibernate.query.sqm.BinaryArithmeticOperator; import org.hibernate.query.sqm.ComparisonOperator; import org.hibernate.query.sqm.FrameKind; @@ -205,10 +208,11 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, private final String uuid; private final String name; - private final transient boolean jpaComplianceEnabled; + private final transient JpaCompliance jpaCompliance; private final transient QueryEngine queryEngine; - private final transient Supplier sessionFactory; private transient ValueHandlingMode criteriaValueHandlingMode; + private final transient ImmutableEntityUpdateQueryHandlingMode immutableEntityUpdateQueryHandlingMode; + private final transient BindingContext bindingContext; private transient BasicType booleanType; private transient BasicType integerType; private transient BasicType longType; @@ -220,15 +224,15 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, public SqmCriteriaNodeBuilder( String uuid, String name, QueryEngine queryEngine, - boolean jpaComplianceEnabled, - ValueHandlingMode criteriaValueHandlingMode, - Supplier sessionFactory) { - this.sessionFactory = sessionFactory; + QueryEngineOptions options, + BindingContext bindingContext) { this.queryEngine = queryEngine; this.uuid = uuid; this.name = name; - this.jpaComplianceEnabled = jpaComplianceEnabled; - this.criteriaValueHandlingMode = criteriaValueHandlingMode; + this.jpaCompliance = options.getJpaCompliance(); + this.criteriaValueHandlingMode = options.getCriteriaValueHandlingMode(); + this.immutableEntityUpdateQueryHandlingMode = options.getImmutableEntityUpdateQueryHandlingMode(); + this.bindingContext = bindingContext; // load registered criteria builder extensions this.extensions = new HashMap<>(); for ( CriteriaBuilderExtension extension : ServiceLoader.load( CriteriaBuilderExtension.class ) ) { @@ -243,7 +247,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, @Override public JpaMetamodel getDomainModel() { - return getSessionFactory().getJpaMetamodel(); + return bindingContext.getJpaMetamodel(); } @Override @@ -253,14 +257,18 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, @Override public boolean isJpaQueryComplianceEnabled() { - return jpaComplianceEnabled; + return jpaCompliance.isJpaQueryComplianceEnabled(); } @Override - public SessionFactoryImplementor getSessionFactory() { - return sessionFactory.get(); + public JpaCompliance getJpaCompliance() { + return jpaCompliance; } + @Override + public ImmutableEntityUpdateQueryHandlingMode getImmutableEntityUpdateQueryHandlingMode() { + return immutableEntityUpdateQueryHandlingMode; + } @Override public BasicType getBooleanType() { @@ -329,7 +337,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, @Override public JpaMetamodelImplementor getJpaMetamodel() { - return getSessionFactory().getJpaMetamodel(); + return (JpaMetamodelImplementor) bindingContext.getJpaMetamodel(); } @Override @@ -349,8 +357,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, @Override public SqmSelectStatement createQuery(String hql, Class resultClass) { final SqmStatement statement = - sessionFactory.get().getQueryEngine().getHqlTranslator() - .translate( hql, resultClass ); + queryEngine.getHqlTranslator().translate( hql, resultClass ); if ( statement instanceof SqmSelectStatement ) { return new SqmSelectStatement<>( (SqmSelectStatement) statement ); } @@ -1545,7 +1552,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, @Override public SqmLiteral literal(T value) { if ( value == null ) { - if ( jpaComplianceEnabled ) { + if ( jpaCompliance.isJpaQueryComplianceEnabled() ) { throw new IllegalArgumentException( "literal value cannot be null" ); } return new SqmLiteralNull<>( this ); @@ -1553,13 +1560,14 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, else { final BindableType valueParamType = getParameterBindType( value ); final SqmExpressible sqmExpressible = - valueParamType == null ? null : valueParamType.resolveExpressible( getSessionFactory() ); + valueParamType == null ? null : valueParamType.resolveExpressible( this ); return new SqmLiteral<>( value, sqmExpressible, this ); } } - private MappingMetamodelImplementor getMappingMetamodel() { - return getSessionFactory().getMappingMetamodel(); + @Override + public MappingMetamodelImplementor getMappingMetamodel() { + return (MappingMetamodelImplementor) bindingContext.getMappingMetamodel(); } @Override @@ -2086,7 +2094,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, } else { return bindableType.getBindableJavaType().isInstance( value ) - || bindableType.resolveExpressible( getSessionFactory() ).getExpressibleJavaType().isInstance( value ); + || bindableType.resolveExpressible( this ).getExpressibleJavaType().isInstance( value ); } } @@ -2128,7 +2136,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, return new ValueBindJpaCriteriaParameter<>( bindableType, value, this ); } final T coercedValue = - bindableType.resolveExpressible( getSessionFactory() ).getExpressibleJavaType() + bindableType.resolveExpressible( this ).getExpressibleJavaType() .coerce(value, this::getTypeConfiguration ); if ( isInstance( bindableType, coercedValue ) ) { return new ValueBindJpaCriteriaParameter<>( bindableType, coercedValue, this ); @@ -2151,7 +2159,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, } DomainType elementType = null; if ( bindableType != null ) { - final SqmExpressible sqmExpressible = bindableType.resolveExpressible( getSessionFactory() ); + final SqmExpressible sqmExpressible = bindableType.resolveExpressible( this ); elementType = sqmExpressible.getSqmType(); } if ( elementType == null ) { @@ -2958,6 +2966,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext, * * @throws InvalidObjectException Thrown if we could not resolve the factory by uuid/name. */ + @Serial private Object readResolve() throws InvalidObjectException { LOG.trace( "Resolving serialized SqmCriteriaNodeBuilder" ); return locateSessionFactoryOnDeserialization( uuid, name ).getCriteriaBuilder(); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java index fbbc0e7103..ccca224ca0 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java @@ -24,6 +24,7 @@ import java.util.function.Function; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jpa.spi.JpaCompliance; import org.hibernate.metamodel.MappingMetamodel; import org.hibernate.metamodel.mapping.BasicValuedMapping; import org.hibernate.metamodel.mapping.Bindable; @@ -307,17 +308,15 @@ public class SqmUtil { } while (declaringType.getPersistenceType() != Type.PersistenceType.ENTITY ); pathBuilder.insert(0, '.'); pathBuilder.insert( 0, attribute.getName() ); - final EntityPersister entityDescriptor = sqmJoin.nodeBuilder() - .getSessionFactory() - .getMappingMetamodel() - .getEntityDescriptor( ( (EntityDomainType) declaringType ).getHibernateEntityName() ); + final EntityPersister entityDescriptor = + sqmJoin.nodeBuilder().getMappingMetamodel() + .getEntityDescriptor( ( (EntityDomainType) declaringType ).getHibernateEntityName() ); return (EntityAssociationMapping) entityDescriptor.findByPath( pathBuilder.toString() ); } else { - final EntityPersister entityDescriptor = sqmJoin.nodeBuilder() - .getSessionFactory() - .getMappingMetamodel() - .getEntityDescriptor( ( (EntityDomainType) declaringType ).getHibernateEntityName() ); + final EntityPersister entityDescriptor = + sqmJoin.nodeBuilder().getMappingMetamodel() + .getEntityDescriptor( ( (EntityDomainType) declaringType ).getHibernateEntityName() ); return (EntityAssociationMapping) entityDescriptor.findAttributeMapping( attribute.getName() ); } } @@ -999,7 +998,7 @@ public class SqmUtil { } private static void checkQueryReturnType(SqmQuerySpec querySpec, Class expectedResultClass) { - final SessionFactoryImplementor sessionFactory = querySpec.nodeBuilder().getSessionFactory(); + final JpaCompliance jpaCompliance = querySpec.nodeBuilder().getJpaCompliance(); final List> selections = querySpec.getSelectClause().getSelections(); if ( selections == null || selections.isEmpty() ) { // make sure there is at least one root @@ -1009,7 +1008,7 @@ public class SqmUtil { } // if there is a single root, use that as the selection if ( sqmRoots.size() == 1 ) { - verifySingularSelectionType( expectedResultClass, sessionFactory, sqmRoots.get( 0 ) ); + verifySingularSelectionType( expectedResultClass, jpaCompliance, sqmRoots.get( 0 ) ); } else { throw new IllegalArgumentException( "Criteria has multiple query roots" ); @@ -1023,17 +1022,17 @@ public class SqmUtil { ? expectedResultClass.getComponentType() : expectedResultClass; for ( JpaSelection selection : selectableNode.getSelectionItems() ) { - verifySelectionType( expectedSelectItemType, sessionFactory, (SqmSelectableNode) selection ); + verifySelectionType( expectedSelectItemType, jpaCompliance, (SqmSelectableNode) selection ); } } else { - verifySingularSelectionType( expectedResultClass, sessionFactory, sqmSelection.getSelectableNode() ); + verifySingularSelectionType( expectedResultClass, jpaCompliance, sqmSelection.getSelectableNode() ); } } else if ( expectedResultClass.isArray() ) { final Class componentType = expectedResultClass.getComponentType(); for ( SqmSelection selection : selections ) { - verifySelectionType( componentType, sessionFactory, selection.getSelectableNode() ); + verifySelectionType( componentType, jpaCompliance, selection.getSelectableNode() ); } } } @@ -1050,10 +1049,10 @@ public class SqmUtil { */ private static void verifySingularSelectionType( Class expectedResultClass, - SessionFactoryImplementor sessionFactory, + JpaCompliance jpaCompliance, SqmSelectableNode selectableNode) { try { - verifySelectionType( expectedResultClass, sessionFactory, selectableNode ); + verifySelectionType( expectedResultClass, jpaCompliance, selectableNode ); } catch (QueryTypeMismatchException mismatchException) { // Check for special case of a single selection item and implicit instantiation. @@ -1084,7 +1083,7 @@ public class SqmUtil { private static void verifySelectionType( Class expectedResultClass, - SessionFactoryImplementor sessionFactory, + JpaCompliance jpaCompliance, SqmSelectableNode selection) { // special case for parameters in the select list if ( selection instanceof SqmParameter ) { @@ -1097,18 +1096,18 @@ public class SqmUtil { } } - if ( !sessionFactory.getSessionFactoryOptions().getJpaCompliance().isJpaQueryComplianceEnabled() ) { + if ( !jpaCompliance.isJpaQueryComplianceEnabled() ) { verifyResultType( expectedResultClass, selection.getExpressible() ); } } public static boolean isResultTypeAlwaysAllowed(Class expectedResultClass) { return expectedResultClass == null - || expectedResultClass == Object.class - || expectedResultClass == Object[].class - || expectedResultClass == List.class - || expectedResultClass == Map.class - || expectedResultClass == Tuple.class; + || expectedResultClass == Object.class + || expectedResultClass == Object[].class + || expectedResultClass == List.class + || expectedResultClass == Map.class + || expectedResultClass == Tuple.class; } protected static void verifyResultType(Class resultClass, @Nullable SqmExpressible selectionExpressible) { diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/TypecheckUtil.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/TypecheckUtil.java index d44a614cf9..35e0cd572a 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/TypecheckUtil.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/TypecheckUtil.java @@ -8,7 +8,6 @@ package org.hibernate.query.sqm.internal; import jakarta.persistence.criteria.Expression; import jakarta.persistence.metamodel.EntityType; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.EmbeddableDomainType; @@ -16,6 +15,7 @@ import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.TupleType; import org.hibernate.metamodel.model.domain.internal.EntityDiscriminatorSqmPathSource; import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.query.BindingContext; import org.hibernate.query.SemanticException; import org.hibernate.query.sqm.BinaryArithmeticOperator; import org.hibernate.query.sqm.SqmExpressible; @@ -29,7 +29,6 @@ import org.hibernate.query.sqm.tree.expression.SqmLiteralNull; import org.hibernate.type.BasicPluralType; import org.hibernate.type.BasicType; import org.hibernate.type.QueryParameterJavaObjectType; -import org.hibernate.type.descriptor.converter.spi.BasicValueConverter; import org.hibernate.type.descriptor.jdbc.JdbcType; import java.time.temporal.Temporal; @@ -77,8 +76,8 @@ import static org.hibernate.type.descriptor.java.JavaTypeHelper.isUnknown; * function application) is legal only when the entity types belong to the same mapped * entity hierarchy. * - * @see #assertComparable(Expression, Expression, SessionFactoryImplementor) - * @see #assertAssignable(String, SqmPath, SqmTypedNode, SessionFactoryImplementor) + * @see #assertComparable(Expression, Expression, BindingContext) + * @see #assertAssignable(String, SqmPath, SqmTypedNode, BindingContext) * * @author Gavin King */ @@ -100,12 +99,12 @@ public class TypecheckUtil { * @param lhsType the type of the expression on the LHS of the comparison operator * @param rhsType the type of the expression on the RHS of the comparison operator * - * @see #isTypeAssignable(SqmPathSource, SqmExpressible, SessionFactoryImplementor) + * @see #isTypeAssignable(SqmPathSource, SqmExpressible, BindingContext) */ public static boolean areTypesComparable( SqmExpressible lhsType, SqmExpressible rhsType, - SessionFactoryImplementor factory) { + BindingContext bindingContext) { if ( lhsType == null || rhsType == null || lhsType == rhsType ) { return true; } @@ -139,7 +138,7 @@ public class TypecheckUtil { // for tuple constructors, we must check each element if ( lhsDomainType instanceof TupleType && rhsDomainType instanceof TupleType ) { - return areTupleTypesComparable( factory, (TupleType) lhsDomainType, (TupleType) rhsDomainType ); + return areTupleTypesComparable(bindingContext, (TupleType) lhsDomainType, (TupleType) rhsDomainType ); } // allow comparing an embeddable against a tuple literal @@ -153,17 +152,17 @@ public class TypecheckUtil { // entities can be compared if they belong to the same inheritance hierarchy if ( lhsDomainType instanceof EntityType && rhsDomainType instanceof EntityType ) { - return areEntityTypesComparable( (EntityType) lhsDomainType, (EntityType) rhsDomainType, factory ); + return areEntityTypesComparable( (EntityType) lhsDomainType, (EntityType) rhsDomainType, bindingContext); } // entities can be compared to discriminators if they belong to // the same inheritance hierarchy if ( lhsDomainType instanceof EntityDiscriminatorSqmPathSource ) { - return isDiscriminatorTypeComparable( (EntityDiscriminatorSqmPathSource) lhsDomainType, rhsDomainType, factory ); + return isDiscriminatorTypeComparable( (EntityDiscriminatorSqmPathSource) lhsDomainType, rhsDomainType, bindingContext); } if ( rhsDomainType instanceof EntityDiscriminatorSqmPathSource ) { - return isDiscriminatorTypeComparable( (EntityDiscriminatorSqmPathSource) rhsDomainType, lhsDomainType, factory ); + return isDiscriminatorTypeComparable( (EntityDiscriminatorSqmPathSource) rhsDomainType, lhsDomainType, bindingContext); } // Treat the expressions as comparable if they belong to the same @@ -173,7 +172,7 @@ public class TypecheckUtil { // enums, user-defined types, etc. if ( lhsDomainType instanceof JdbcMapping && rhsDomainType instanceof JdbcMapping ) { - if ( areJdbcMappingsComparable( (JdbcMapping) lhsDomainType, (JdbcMapping) rhsDomainType, factory ) ) { + if ( areJdbcMappingsComparable( (JdbcMapping) lhsDomainType, (JdbcMapping) rhsDomainType, bindingContext) ) { return true; } } @@ -195,14 +194,14 @@ public class TypecheckUtil { private static boolean areJdbcMappingsComparable( JdbcMapping lhsJdbcMapping, JdbcMapping rhsJdbcMapping, - SessionFactoryImplementor factory) { + BindingContext bindingContext) { if ( areJdbcTypesComparable( lhsJdbcMapping.getJdbcType(), rhsJdbcMapping.getJdbcType() ) ) { return true; } // converters are implicitly applied to the other side when its domain type is compatible else if ( lhsJdbcMapping.getValueConverter() != null || rhsJdbcMapping.getValueConverter() != null ) { - final JdbcMapping lhsDomainMapping = getDomainJdbcType( lhsJdbcMapping, factory ); - final JdbcMapping rhsDomainMapping = getDomainJdbcType( rhsJdbcMapping, factory ); + final JdbcMapping lhsDomainMapping = getDomainJdbcType( lhsJdbcMapping, bindingContext); + final JdbcMapping rhsDomainMapping = getDomainJdbcType( rhsJdbcMapping, bindingContext); return lhsDomainMapping != null && rhsDomainMapping != null && areJdbcTypesComparable( lhsDomainMapping.getJdbcType(), rhsDomainMapping.getJdbcType() @@ -220,11 +219,11 @@ public class TypecheckUtil { || lhsJdbcType.isNumber() && rhsJdbcType.isNumber(); } - private static JdbcMapping getDomainJdbcType(JdbcMapping jdbcMapping, SessionFactoryImplementor factory) { + private static JdbcMapping getDomainJdbcType(JdbcMapping jdbcMapping, BindingContext bindingContext) { if ( jdbcMapping.getValueConverter() != null ) { - final BasicType basicType = factory.getTypeConfiguration().getBasicTypeForJavaType( - jdbcMapping.getValueConverter().getDomainJavaType().getJavaType() - ); + final BasicType basicType = + bindingContext.getTypeConfiguration() + .getBasicTypeForJavaType( jdbcMapping.getValueConverter().getDomainJavaType().getJavaType() ); if ( basicType != null ) { return basicType.getJdbcMapping(); } @@ -255,7 +254,7 @@ public class TypecheckUtil { } private static boolean areTupleTypesComparable( - SessionFactoryImplementor factory, + BindingContext bindingContext, TupleType lhsTuple, TupleType rhsTuple) { if ( rhsTuple.componentCount() != lhsTuple.componentCount() ) { @@ -263,7 +262,7 @@ public class TypecheckUtil { } else { for ( int i = 0; i < lhsTuple.componentCount(); i++ ) { - if ( !areTypesComparable( lhsTuple.get(i), rhsTuple.get(i), factory ) ) { + if ( !areTypesComparable( lhsTuple.get(i), rhsTuple.get(i), bindingContext) ) { return false; } } @@ -273,32 +272,32 @@ public class TypecheckUtil { private static boolean areEntityTypesComparable( EntityType lhsType, EntityType rhsType, - SessionFactoryImplementor factory) { - EntityPersister lhsEntity = getEntityDescriptor( factory, lhsType.getName() ); - EntityPersister rhsEntity = getEntityDescriptor( factory, rhsType.getName() ); + BindingContext bindingContext) { + EntityPersister lhsEntity = getEntityDescriptor(bindingContext, lhsType.getName() ); + EntityPersister rhsEntity = getEntityDescriptor(bindingContext, rhsType.getName() ); return lhsEntity.getRootEntityName().equals( rhsEntity.getRootEntityName() ); } private static boolean isDiscriminatorTypeComparable( EntityDiscriminatorSqmPathSource lhsDiscriminator, SqmExpressible rhsType, - SessionFactoryImplementor factory) { + BindingContext bindingContext) { String entityName = lhsDiscriminator.getEntityDomainType().getHibernateEntityName(); - EntityPersister lhsEntity = factory.getMappingMetamodel().getEntityDescriptor( entityName ); + EntityPersister lhsEntity = bindingContext.getMappingMetamodel().getEntityDescriptor( entityName ); if ( rhsType instanceof EntityType ) { String rhsEntityName = ((EntityType) rhsType).getName(); - EntityPersister rhsEntity = getEntityDescriptor( factory, rhsEntityName ); + EntityPersister rhsEntity = getEntityDescriptor(bindingContext, rhsEntityName ); return lhsEntity.getRootEntityName().equals( rhsEntity.getRootEntityName() ); } else if ( rhsType instanceof EntityDiscriminatorSqmPathSource ) { EntityDiscriminatorSqmPathSource discriminator = (EntityDiscriminatorSqmPathSource) rhsType; String rhsEntityName = discriminator.getEntityDomainType().getHibernateEntityName(); - EntityPersister rhsEntity = factory.getMappingMetamodel().getEntityDescriptor( rhsEntityName ); + EntityPersister rhsEntity = bindingContext.getMappingMetamodel().getEntityDescriptor( rhsEntityName ); return rhsEntity.getRootEntityName().equals( lhsEntity.getRootEntityName() ); } else { BasicType discriminatorType = (BasicType) lhsDiscriminator.getEntityMapping().getDiscriminatorMapping().getMappedType(); - return areTypesComparable( discriminatorType, rhsType, factory ); + return areTypesComparable( discriminatorType, rhsType, bindingContext); } } @@ -306,11 +305,11 @@ public class TypecheckUtil { * @param targetType the type of the path expression to which a value is assigned * @param expressionType the type of the value expression being assigned to the path * - * @see #areTypesComparable(SqmExpressible, SqmExpressible, SessionFactoryImplementor) + * @see #areTypesComparable(SqmExpressible, SqmExpressible, BindingContext) */ private static boolean isTypeAssignable( SqmPathSource targetType, SqmExpressible expressionType, - SessionFactoryImplementor factory) { + BindingContext bindingContext) { if ( targetType == null || expressionType == null || targetType == expressionType ) { return true; @@ -319,7 +318,7 @@ public class TypecheckUtil { // entities can be assigned if they belong to the same inheritance hierarchy if ( targetType instanceof EntityType && expressionType instanceof EntityType ) { - return isEntityTypeAssignable( (EntityType) targetType, (EntityType) expressionType, factory ); + return isEntityTypeAssignable( (EntityType) targetType, (EntityType) expressionType, bindingContext); } // Treat the expression as assignable to the target path if they belong @@ -367,21 +366,21 @@ public class TypecheckUtil { private static boolean isEntityTypeAssignable( EntityType lhsType, EntityType rhsType, - SessionFactoryImplementor factory) { - EntityPersister lhsEntity = getEntityDescriptor( factory, lhsType.getName() ); - EntityPersister rhsEntity = getEntityDescriptor( factory, rhsType.getName() ); + BindingContext bindingContext) { + EntityPersister lhsEntity = getEntityDescriptor(bindingContext, lhsType.getName() ); + EntityPersister rhsEntity = getEntityDescriptor(bindingContext, rhsType.getName() ); return lhsEntity.isSubclassEntityName( rhsEntity.getEntityName() ); } - private static EntityPersister getEntityDescriptor(SessionFactoryImplementor factory, String name) { - return factory.getMappingMetamodel() - .getEntityDescriptor( factory.getJpaMetamodel().qualifyImportableName( name ) ); + private static EntityPersister getEntityDescriptor(BindingContext bindingContext, String name) { + return bindingContext.getMappingMetamodel() + .getEntityDescriptor( bindingContext.getJpaMetamodel().qualifyImportableName( name ) ); } /** - * @see TypecheckUtil#assertAssignable(String, SqmPath, SqmTypedNode, SessionFactoryImplementor) + * @see TypecheckUtil#assertAssignable(String, SqmPath, SqmTypedNode, BindingContext) */ - public static void assertComparable(Expression x, Expression y, SessionFactoryImplementor factory) { + public static void assertComparable(Expression x, Expression y, BindingContext bindingContext) { final SqmExpression left = (SqmExpression) x; final SqmExpression right = (SqmExpression) y; final Integer leftTupleLength = left.getTupleLength(); @@ -401,7 +400,7 @@ public class TypecheckUtil { if ( !( left instanceof SqmLiteralNull ) && !( right instanceof SqmLiteralNull ) ) { final SqmExpressible leftType = left.getExpressible(); final SqmExpressible rightType = right.getExpressible(); - if ( !areTypesComparable( leftType, rightType, factory ) ) { + if ( !areTypesComparable( leftType, rightType, bindingContext) ) { throw new SemanticException( String.format( "Cannot compare left expression of type '%s' with right expression of type '%s'", @@ -414,12 +413,12 @@ public class TypecheckUtil { } /** - * @see TypecheckUtil#assertComparable(Expression, Expression, SessionFactoryImplementor) + * @see TypecheckUtil#assertComparable(Expression, Expression, BindingContext) */ public static void assertAssignable( String hqlString, SqmPath targetPath, SqmTypedNode expression, - SessionFactoryImplementor factory) { + BindingContext bindingContext) { // allow assigning literal null to things if ( expression instanceof SqmLiteralNull ) { // TODO: check that the target path is nullable @@ -427,7 +426,7 @@ public class TypecheckUtil { else { SqmPathSource targetType = targetPath.getNodeType(); SqmExpressible expressionType = expression.getNodeType(); - if ( !isTypeAssignable( targetType, expressionType, factory ) ) { + if ( !isTypeAssignable( targetType, expressionType, bindingContext) ) { throw new SemanticException( String.format( "Cannot assign expression of type '%s' to target path '%s' of type '%s'", diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/spi/SqmCreationContext.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/spi/SqmCreationContext.java index 4ffc5a264f..b4381eae49 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/spi/SqmCreationContext.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/spi/SqmCreationContext.java @@ -8,6 +8,7 @@ package org.hibernate.query.sqm.spi; import org.hibernate.Incubating; import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; +import org.hibernate.query.BindingContext; import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.service.ServiceRegistry; @@ -19,7 +20,7 @@ import org.hibernate.type.spi.TypeConfiguration; * @author Steve Ebersole */ @Incubating -public interface SqmCreationContext { +public interface SqmCreationContext extends BindingContext { /** * Access to the domain model metadata */ diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java index 4baec07486..add21d46c2 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java @@ -6162,7 +6162,7 @@ public abstract class BaseSqmToSqlAstConverter extends Base } } - final SqmExpressible paramSqmType = paramType.resolveExpressible( creationContext.getSessionFactory() ); + final SqmExpressible paramSqmType = paramType.resolveExpressible( creationContext ); if ( paramSqmType instanceof SqmPath ) { final MappingModelExpressible modelPart = determineValueMapping( (SqmPath) paramSqmType ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPath.java index 6d7667d68a..f7f050b451 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPath.java @@ -196,7 +196,7 @@ public abstract class AbstractSqmPath extends AbstractSqmExpression implem @SuppressWarnings("unchecked") public SqmPath get(String attributeName) { final SqmPathSource subNavigable = - getResolvedModel().getSubPathSource( attributeName, nodeBuilder().getSessionFactory().getJpaMetamodel() ); + getResolvedModel().getSubPathSource( attributeName, nodeBuilder().getJpaMetamodel() ); return resolvePath( attributeName, subNavigable ); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/JpaCriteriaParameter.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/JpaCriteriaParameter.java index e0be17f5c2..c198f9d69f 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/JpaCriteriaParameter.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/JpaCriteriaParameter.java @@ -54,7 +54,7 @@ public class JpaCriteriaParameter if ( type == null ) { return null; } - return type.resolveExpressible( nodeBuilder.getSessionFactory() ); + return type.resolveExpressible( nodeBuilder ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmExpressionHelper.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmExpressionHelper.java index 6940e41d7e..7a919ec5f2 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmExpressionHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmExpressionHelper.java @@ -15,9 +15,9 @@ import java.time.LocalDateTime; import java.time.LocalTime; import java.time.OffsetTime; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.metamodel.model.domain.internal.EmbeddedSqmPathSource; import org.hibernate.query.BindableType; +import org.hibernate.query.BindingContext; import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.sqm.BinaryArithmeticOperator; @@ -37,26 +37,18 @@ import org.hibernate.usertype.internal.OffsetTimeCompositeUserType; */ public class SqmExpressionHelper { public static SqmExpressible toSqmType(BindableType parameterType, SqmCreationState creationState) { - return toSqmType( parameterType, creationState.getCreationContext().getNodeBuilder().getSessionFactory() ); + return toSqmType( parameterType, creationState.getCreationContext() ); } - public static SqmExpressible toSqmType(BindableType anticipatedType, NodeBuilder nodeBuilder) { - return toSqmType( anticipatedType, nodeBuilder.getSessionFactory() ); - } - -// public static SqmExpressible toSqmType(BindableType anticipatedType, TypeConfiguration typeConfiguration) { -// return toSqmType( anticipatedType, typeConfiguration.getSessionFactory() ); -// } - - public static SqmExpressible toSqmType(BindableType anticipatedType, SessionFactoryImplementor sessionFactory) { + public static SqmExpressible toSqmType( + BindableType anticipatedType, BindingContext bindingContext) { if ( anticipatedType == null ) { return null; } - final SqmExpressible sqmExpressible = anticipatedType.resolveExpressible( sessionFactory ); + final SqmExpressible sqmExpressible = anticipatedType.resolveExpressible(bindingContext); assert sqmExpressible != null; return sqmExpressible; - } public static SqmLiteral timestampLiteralFrom(String literalText, SqmCreationState creationState) { diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/insert/AbstractSqmInsertStatement.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/insert/AbstractSqmInsertStatement.java index ebe84ed55e..df91cff68a 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/insert/AbstractSqmInsertStatement.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/insert/AbstractSqmInsertStatement.java @@ -90,11 +90,11 @@ public abstract class AbstractSqmInsertStatement extends AbstractSqmDmlStatem null ); } - final SessionFactoryImplementor factory = nodeBuilder().getSessionFactory(); + for ( int i = 0; i < expressionsSize; i++ ) { final SqmTypedNode expression = expressions.get( i ); final SqmPath targetPath = insertionTargetPaths.get(i); - assertAssignable( null, targetPath, expression, factory ); + assertAssignable( null, targetPath, expression, nodeBuilder() ); // if ( expression.getNodeJavaType() == null ) { // continue; // } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/insert/SqmConflictUpdateAction.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/insert/SqmConflictUpdateAction.java index 4f713b12f6..ebf93008ba 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/insert/SqmConflictUpdateAction.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/insert/SqmConflictUpdateAction.java @@ -83,7 +83,7 @@ public class SqmConflictUpdateAction implements SqmNode, JpaConflictUpdateAct else { expression = (SqmExpression) nodeBuilder().value( value ); } - assertAssignable( null, sqmPath, expression, nodeBuilder().getSessionFactory() ); + assertAssignable( null, sqmPath, expression, nodeBuilder() ); applyAssignment( sqmPath, expression ); return this; } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmBetweenPredicate.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmBetweenPredicate.java index f015c12a09..ad32ec85bd 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmBetweenPredicate.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmBetweenPredicate.java @@ -34,8 +34,8 @@ public class SqmBetweenPredicate extends AbstractNegatableSqmPredicate { this.lowerBound = lowerBound; this.upperBound = upperBound; - assertComparable( expression, lowerBound, nodeBuilder.getSessionFactory() ); - assertComparable( expression, upperBound, nodeBuilder.getSessionFactory() ); + assertComparable( expression, lowerBound, nodeBuilder ); + assertComparable( expression, upperBound, nodeBuilder ); final SqmExpressible expressibleType = QueryHelper.highestPrecedenceType( expression.getExpressible(), diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmComparisonPredicate.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmComparisonPredicate.java index 3a5d11e7e0..3b88304802 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmComparisonPredicate.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmComparisonPredicate.java @@ -43,7 +43,7 @@ public class SqmComparisonPredicate extends AbstractNegatableSqmPredicate { this.rightHandExpression = rightHandExpression; this.operator = operator; - assertComparable( leftHandExpression, rightHandExpression, nodeBuilder.getSessionFactory() ); + assertComparable( leftHandExpression, rightHandExpression, nodeBuilder ); final SqmExpressible expressibleType = QueryHelper.highestPrecedenceType( leftHandExpression.getExpressible(), @@ -59,7 +59,7 @@ public class SqmComparisonPredicate extends AbstractNegatableSqmPredicate { this.leftHandExpression = affirmativeForm.leftHandExpression; this.rightHandExpression = affirmativeForm.rightHandExpression; this.operator = affirmativeForm.operator; - assertComparable( leftHandExpression, rightHandExpression, nodeBuilder().getSessionFactory() ); + assertComparable( leftHandExpression, rightHandExpression, nodeBuilder() ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmInListPredicate.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmInListPredicate.java index 64eef0b08a..9b591ec49f 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmInListPredicate.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmInListPredicate.java @@ -136,7 +136,7 @@ public class SqmInListPredicate extends AbstractNegatableSqmPredicate impleme } private void implyListElementType(SqmExpression expression) { - assertComparable( getTestExpression(), expression, nodeBuilder().getSessionFactory() ); + assertComparable( getTestExpression(), expression, nodeBuilder() ); expression.applyInferableType( QueryHelper.highestPrecedenceType2( getTestExpression().getExpressible(), expression.getExpressible() ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmInSubQueryPredicate.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmInSubQueryPredicate.java index d44532c2df..571cfed1fb 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmInSubQueryPredicate.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmInSubQueryPredicate.java @@ -42,7 +42,7 @@ public class SqmInSubQueryPredicate extends AbstractNegatableSqmPredicate imp this.testExpression = testExpression; this.subQueryExpression = subQueryExpression; - assertComparable( testExpression, subQueryExpression, nodeBuilder.getSessionFactory() ); + assertComparable( testExpression, subQueryExpression, nodeBuilder ); final SqmExpressible expressibleType = QueryHelper.highestPrecedenceType2( testExpression.getExpressible(), diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmMemberOfPredicate.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmMemberOfPredicate.java index 8276908064..fa10ab3661 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmMemberOfPredicate.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/predicate/SqmMemberOfPredicate.java @@ -39,7 +39,7 @@ public class SqmMemberOfPredicate extends AbstractNegatableSqmPredicate { final SimpleDomainType simpleDomainType = pluralPath.getReferencedPathSource().getElementType(); - if ( !areTypesComparable(leftHandExpression.getNodeType(), simpleDomainType, nodeBuilder.getSessionFactory()) ) { + if ( !areTypesComparable( leftHandExpression.getNodeType(), simpleDomainType, nodeBuilder ) ) { throw new SemanticException( String.format( "Cannot compare left expression of type '%s' with right expression of type '%s'", diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/update/SqmUpdateStatement.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/update/SqmUpdateStatement.java index ced72d33b3..8c0217853b 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/update/SqmUpdateStatement.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/update/SqmUpdateStatement.java @@ -12,7 +12,6 @@ import java.util.Map; import java.util.Set; import org.hibernate.HibernateException; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.persister.entity.EntityPersister; @@ -37,10 +36,8 @@ import org.hibernate.query.sqm.tree.from.SqmRoot; import org.hibernate.query.sqm.tree.select.SqmSubQuery; import jakarta.persistence.criteria.Expression; -import jakarta.persistence.criteria.ParameterExpression; import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Predicate; -import jakarta.persistence.criteria.Subquery; import jakarta.persistence.metamodel.EntityType; import jakarta.persistence.metamodel.SingularAttribute; import org.checkerframework.checker.nullness.qual.Nullable; @@ -135,12 +132,11 @@ public class SqmUpdateStatement } private void verifyImmutableEntityUpdate(String hql) { - final SessionFactoryImplementor factory = nodeBuilder().getSessionFactory(); final EntityPersister persister = - factory.getMappingMetamodel().getEntityDescriptor( getTarget().getEntityName() ); + nodeBuilder().getMappingMetamodel().getEntityDescriptor( getTarget().getEntityName() ); if ( !persister.isMutable() ) { final ImmutableEntityUpdateQueryHandlingMode mode = - factory.getSessionFactoryOptions().getImmutableEntityUpdateQueryHandlingMode(); + nodeBuilder().getImmutableEntityUpdateQueryHandlingMode(); final String querySpaces = Arrays.toString( persister.getQuerySpaces() ); switch ( mode ) { case WARNING: @@ -155,13 +151,12 @@ public class SqmUpdateStatement } private void verifyUpdateTypesMatch() { - final SessionFactoryImplementor factory = nodeBuilder().getSessionFactory(); final List> assignments = getSetClause().getAssignments(); for ( int i = 0; i < assignments.size(); i++ ) { final SqmAssignment assignment = assignments.get( i ); final SqmPath targetPath = assignment.getTargetPath(); final SqmExpression expression = assignment.getValue(); - assertAssignable( null, targetPath, expression, factory ); + assertAssignable( null, targetPath, expression, nodeBuilder() ); } } @@ -207,7 +202,7 @@ public class SqmUpdateStatement else { expression = (SqmExpression) nodeBuilder().value( value ); } - assertAssignable( null, sqmPath, expression, nodeBuilder().getSessionFactory() ); + assertAssignable( null, sqmPath, expression, nodeBuilder() ); applyAssignment( sqmPath, expression ); return this; } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/SqlAstCreationContext.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/SqlAstCreationContext.java index f4f5d9a524..9b66286714 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/SqlAstCreationContext.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/SqlAstCreationContext.java @@ -8,6 +8,7 @@ package org.hibernate.sql.ast.spi; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.metamodel.spi.MappingMetamodelImplementor; +import org.hibernate.query.BindingContext; import org.hibernate.service.ServiceRegistry; /** @@ -16,7 +17,7 @@ import org.hibernate.service.ServiceRegistry; * * @author Steve Ebersole */ -public interface SqlAstCreationContext { +public interface SqlAstCreationContext extends BindingContext { /** * The SessionFactory */ diff --git a/hibernate-core/src/main/java/org/hibernate/type/BasicTypeReference.java b/hibernate-core/src/main/java/org/hibernate/type/BasicTypeReference.java index fe53a7c815..308918c1de 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/BasicTypeReference.java +++ b/hibernate-core/src/main/java/org/hibernate/type/BasicTypeReference.java @@ -8,7 +8,7 @@ package org.hibernate.type; import java.io.Serializable; -import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.query.BindingContext; import org.hibernate.type.descriptor.converter.spi.BasicValueConverter; import org.hibernate.query.BindableType; import org.hibernate.query.sqm.SqmExpressible; @@ -83,7 +83,7 @@ public final class BasicTypeReference implements BindableType, Serializabl } @Override - public SqmExpressible resolveExpressible(SessionFactoryImplementor sessionFactory) { - return sessionFactory.getTypeConfiguration().getBasicTypeRegistry().resolve( this ); + public SqmExpressible resolveExpressible(BindingContext bindingContext) { + return bindingContext.getTypeConfiguration().getBasicTypeRegistry().resolve( this ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java b/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java index 2533203eba..a73c0b714e 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java @@ -37,6 +37,7 @@ import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess; import org.hibernate.metamodel.spi.EmbeddableInstantiator; import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy; import org.hibernate.property.access.spi.PropertyAccess; +import org.hibernate.query.BindingContext; import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.type.descriptor.ValueExtractor; import org.hibernate.type.descriptor.jdbc.JdbcType; @@ -844,8 +845,8 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen } @Override - public SqmExpressible resolveExpressible(SessionFactoryImplementor sessionFactory) { - return sessionFactory.getJpaMetamodel().embeddable( getReturnedClass() ); + public SqmExpressible resolveExpressible(BindingContext bindingContext) { + return bindingContext.getJpaMetamodel().embeddable( getReturnedClass() ); } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/sqm/BaseSqmUnitTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/sqm/BaseSqmUnitTest.java index d004cc3ff9..2055c65422 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/sqm/BaseSqmUnitTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/sqm/BaseSqmUnitTest.java @@ -12,6 +12,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.loader.ast.spi.AfterLoadAction; import org.hibernate.metamodel.mapping.EntityMappingType; +import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.query.sqm.tree.select.SqmSelectStatement; import org.hibernate.service.ServiceRegistry; @@ -19,6 +20,7 @@ import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.sql.exec.spi.Callback; import org.hibernate.testing.orm.junit.BaseSessionFactoryFunctionalTest; +import org.hibernate.type.spi.TypeConfiguration; /** * @author Steve Ebersole @@ -80,6 +82,16 @@ public abstract class BaseSqmUnitTest return sessionFactory().getRuntimeMetamodels().getMappingMetamodel(); } + @Override + public TypeConfiguration getTypeConfiguration() { + return sessionFactory().getTypeConfiguration(); + } + + @Override + public JpaMetamodel getJpaMetamodel() { + return sessionFactory().getJpaMetamodel(); + } + @Override public ServiceRegistry getServiceRegistry() { return sessionFactory().getServiceRegistry(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/type/contributor/ArrayType.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/contributor/ArrayType.java index 1e0087b638..eacb0d44e7 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/type/contributor/ArrayType.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/contributor/ArrayType.java @@ -6,8 +6,8 @@ import java.sql.ResultSet; import java.sql.SQLException; import org.hibernate.HibernateException; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.query.BindingContext; import org.hibernate.type.descriptor.converter.spi.BasicValueConverter; import org.hibernate.query.BindableType; import org.hibernate.query.sqm.SqmExpressible; @@ -35,7 +35,7 @@ public class ArrayType implements UserType, BindableType, BasicVal } @Override - public SqmExpressible resolveExpressible(SessionFactoryImplementor sessionFactory) { + public SqmExpressible resolveExpressible(BindingContext bindingContext) { // really a UserType should not implement BindableType throw new UnsupportedOperationException(); } diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/MockSessionFactory.java b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/MockSessionFactory.java index 40829be48e..dffba25187 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/MockSessionFactory.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/validation/MockSessionFactory.java @@ -82,7 +82,6 @@ import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.proxy.EntityNotFoundDelegate; -import org.hibernate.query.criteria.ValueHandlingMode; import org.hibernate.query.hql.HqlTranslator; import org.hibernate.query.hql.internal.StandardHqlTranslator; import org.hibernate.query.hql.spi.SqmCreationOptions; @@ -152,6 +151,8 @@ public abstract class MockSessionFactory private final MetadataImplementor bootModel; private final MetadataContext metadataContext; + private final NodeBuilder nodeBuilder; + public MockSessionFactory() { serviceRegistry = StandardServiceRegistryImpl.create( @@ -222,6 +223,8 @@ public abstract class MockSessionFactory functionFactory.hypotheticalOrderedSetAggregates(); functionFactory.windowFunctions(); typeConfiguration.scope((SessionFactoryImplementor) this); + + nodeBuilder = new SqmCriteriaNodeBuilder("", "", this, this, this); } @Override @@ -460,7 +463,7 @@ public abstract class MockSessionFactory @Override public QueryInterpretationCache getInterpretationCache() { - return new QueryInterpretationCacheDisabledImpl(this::getStatistics); + return new QueryInterpretationCacheDisabledImpl( serviceRegistry ); } @Override @@ -475,14 +478,7 @@ public abstract class MockSessionFactory @Override public NodeBuilder getCriteriaBuilder() { - return new SqmCriteriaNodeBuilder( - "", - "", - this, - false, - ValueHandlingMode.INLINE, - () -> MockSessionFactory.this - ); + return nodeBuilder; } @Override