major refactor to horrible instantiation of QueryEngine

This commit is contained in:
Gavin King 2024-09-09 22:59:16 +02:00
parent 2a999d68d2
commit 9f91f2dbff
38 changed files with 287 additions and 227 deletions

View File

@ -287,7 +287,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
} }
@Override @Override
public NamedObjectRepository buildNamedQueryRepository(SessionFactoryImplementor sessionFactory) { public NamedObjectRepository buildNamedQueryRepository() {
throw new UnsupportedOperationException( "#buildNamedQueryRepository should not be called on InFlightMetadataCollector" ); throw new UnsupportedOperationException( "#buildNamedQueryRepository should not be called on InFlightMetadataCollector" );
} }

View File

@ -71,6 +71,7 @@ import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.cfg.AvailableSettings.EVENT_LISTENER_PREFIX; import static org.hibernate.cfg.AvailableSettings.EVENT_LISTENER_PREFIX;
import static org.hibernate.internal.util.StringHelper.splitAtCommas; 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. * Container for configuration data collected during binding the metamodel.
@ -356,12 +357,12 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
} }
@Override @Override
public NamedObjectRepository buildNamedQueryRepository(SessionFactoryImplementor sessionFactory) { public NamedObjectRepository buildNamedQueryRepository() {
return new NamedObjectRepositoryImpl( return new NamedObjectRepositoryImpl(
CollectionHelper.mapOfSize( namedQueryMap.size() ), mapOfSize( namedQueryMap.size() ),
CollectionHelper.mapOfSize( namedNativeQueryMap.size() ), mapOfSize( namedNativeQueryMap.size() ),
CollectionHelper.mapOfSize( namedProcedureCallMap.size() ), mapOfSize( namedProcedureCallMap.size() ),
CollectionHelper.mapOfSize( sqlResultSetMappingMap.size() ) mapOfSize( sqlResultSetMappingMap.size() )
); );
} }

View File

@ -259,8 +259,8 @@ public abstract class AbstractDelegatingMetadata implements MetadataImplementor
} }
@Override @Override
public NamedObjectRepository buildNamedQueryRepository(SessionFactoryImplementor sessionFactory) { public NamedObjectRepository buildNamedQueryRepository() {
return delegate().buildNamedQueryRepository( sessionFactory ); return delegate().buildNamedQueryRepository();
} }
@Override @Override

View File

@ -46,7 +46,7 @@ public interface MetadataImplementor extends Metadata {
*/ */
SqmFunctionRegistry getFunctionRegistry(); SqmFunctionRegistry getFunctionRegistry();
NamedObjectRepository buildNamedQueryRepository(SessionFactoryImplementor sessionFactory); NamedObjectRepository buildNamedQueryRepository();
@Incubating @Incubating
void orderColumns(boolean forceOrdering); void orderColumns(boolean forceOrdering);

View File

@ -25,7 +25,6 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.BaselineSessionEventsListenerBuilder; import org.hibernate.internal.BaselineSessionEventsListenerBuilder;
import org.hibernate.jpa.spi.JpaCompliance; import org.hibernate.jpa.spi.JpaCompliance;
import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
import org.hibernate.query.criteria.ValueHandlingMode; import org.hibernate.query.criteria.ValueHandlingMode;
import org.hibernate.query.spi.QueryEngineOptions; import org.hibernate.query.spi.QueryEngineOptions;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode; import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
@ -242,10 +241,6 @@ public interface SessionFactoryOptions extends QueryEngineOptions {
boolean isFailOnPaginationOverCollectionFetchEnabled(); 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, * 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). * neither explicitly nor implicitly (see the concept of implicit catalog in XML mapping).

View File

@ -227,7 +227,7 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im
settings = getSettings( options, serviceRegistry ); settings = getSettings( options, serviceRegistry );
maskOutSensitiveInformation( settings ); maskOutSensitiveInformation( settings );
deprecationCheck( settings ); deprecationCheck( settings );
LOG.debugf( "Instantiating SessionFactory with settings: %s", settings); LOG.debugf( "Instantiating SessionFactory with settings: %s", settings );
sqlStringGenerationContext = createSqlStringGenerationContext( bootMetamodel, options, jdbcServices ); sqlStringGenerationContext = createSqlStringGenerationContext( bootMetamodel, options, jdbcServices );
@ -280,7 +280,7 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im
// created, then we can split creation of QueryEngine // created, then we can split creation of QueryEngine
// and SqmFunctionRegistry, instantiating just the // and SqmFunctionRegistry, instantiating just the
// registry here, and doing the engine later // 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) // create runtime metamodels (mapping and JPA)
final RuntimeMetamodelsImpl runtimeMetamodelsImpl = new RuntimeMetamodelsImpl(); final RuntimeMetamodelsImpl runtimeMetamodelsImpl = new RuntimeMetamodelsImpl();

View File

@ -7,7 +7,6 @@
package org.hibernate.query; package org.hibernate.query;
import org.hibernate.Incubating; import org.hibernate.Incubating;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmExpressible;
/** /**
@ -30,7 +29,7 @@ public interface BindableType<J> {
} }
/** /**
* Resolve this parameter type to the corresponding SqmExpressible * Resolve this parameter type to the corresponding {@link SqmExpressible}
*/ */
SqmExpressible<J> resolveExpressible(SessionFactoryImplementor sessionFactory); SqmExpressible<J> resolveExpressible(BindingContext bindingContext);
} }

View File

@ -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();
}

View File

@ -13,9 +13,9 @@ import java.time.OffsetTime;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.Calendar; import java.util.Calendar;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.BindableType; import org.hibernate.query.BindableType;
import org.hibernate.query.BindingContext;
import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.java.JavaTypeHelper; import org.hibernate.type.descriptor.java.JavaTypeHelper;
@ -39,9 +39,9 @@ public class BindingTypeHelper {
public <T> BindableType<T> resolveTemporalPrecision( public <T> BindableType<T> resolveTemporalPrecision(
TemporalType precision, TemporalType precision,
BindableType<T> declaredParameterType, BindableType<T> declaredParameterType,
SessionFactoryImplementor sessionFactory) { BindingContext bindingContext) {
if ( precision != null ) { if ( precision != null ) {
final SqmExpressible<T> sqmExpressible = declaredParameterType.resolveExpressible( sessionFactory ); final SqmExpressible<T> sqmExpressible = declaredParameterType.resolveExpressible(bindingContext);
if ( !( JavaTypeHelper.isTemporal( sqmExpressible.getExpressibleJavaType() ) ) ) { if ( !( JavaTypeHelper.isTemporal( sqmExpressible.getExpressibleJavaType() ) ) ) {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"Cannot treat non-temporal parameter type with temporal precision" "Cannot treat non-temporal parameter type with temporal precision"
@ -50,7 +50,7 @@ public class BindingTypeHelper {
final TemporalJavaType<T> temporalJtd = (TemporalJavaType<T>) sqmExpressible.getExpressibleJavaType(); final TemporalJavaType<T> temporalJtd = (TemporalJavaType<T>) sqmExpressible.getExpressibleJavaType();
if ( temporalJtd.getPrecision() != precision ) { if ( temporalJtd.getPrecision() != precision ) {
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration(); final TypeConfiguration typeConfiguration = bindingContext.getTypeConfiguration();
final TemporalJavaType<T> temporalTypeForPrecision; final TemporalJavaType<T> temporalTypeForPrecision;
// Special case java.util.Date, because TemporalJavaType#resolveTypeForPrecision doesn't support widening, // 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 // since the main purpose of that method is to determine the final java type based on the reflective type

View File

@ -10,13 +10,13 @@ import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.FunctionContributor; import org.hibernate.boot.model.FunctionContributor;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.query.spi.NativeQueryInterpreter; import org.hibernate.engine.query.spi.NativeQueryInterpreter;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.query.BindingContext;
import org.hibernate.query.hql.HqlTranslator; import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.hql.internal.StandardHqlTranslator; import org.hibernate.query.hql.internal.StandardHqlTranslator;
import org.hibernate.query.hql.spi.SqmCreationOptions; 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.SqmTranslatorFactory;
import org.hibernate.query.sqm.sql.StandardSqmTranslatorFactory; import org.hibernate.query.sqm.sql.StandardSqmTranslatorFactory;
import org.hibernate.service.ServiceRegistry; 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.hibernate.type.spi.TypeConfiguration;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -40,7 +40,6 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Supplier;
import static java.util.Comparator.comparingInt; 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"); private static final Logger LOG_HQL_FUNCTIONS = CoreLogging.logger("org.hibernate.HQL_FUNCTIONS");
public static QueryEngine from(SessionFactoryImplementor sessionFactory, MetadataImplementor metadata) { public static QueryEngineImpl from(
final QueryEngineOptions options = sessionFactory.getSessionFactoryOptions(); MetadataImplementor metadata,
final Dialect dialect = sessionFactory.getJdbcServices().getDialect(); QueryEngineOptions options,
SqmCreationContext sqmCreationContext,
ServiceRegistryImplementor serviceRegistry,
Map<String,Object> properties,
String name) {
final Dialect dialect = serviceRegistry.requireService( JdbcServices.class ).getDialect();
return new QueryEngineImpl( return new QueryEngineImpl(
sessionFactory,
metadata.getTypeConfiguration(), metadata.getTypeConfiguration(),
resolveHqlTranslator( options, dialect, sessionFactory, new SqmCreationOptionsStandard( options ) ), resolveHqlTranslator( options, dialect, sqmCreationContext, new SqmCreationOptionsStandard( options ) ),
resolveSqmTranslatorFactory( options, dialect ), resolveSqmTranslatorFactory( options, dialect ),
createFunctionRegistry( sessionFactory, metadata, options, dialect ), createFunctionRegistry( serviceRegistry, metadata, options, dialect ),
metadata.buildNamedQueryRepository( sessionFactory ), metadata.buildNamedQueryRepository(),
buildInterpretationCache( sessionFactory::getStatistics, sessionFactory.getProperties() ), buildInterpretationCache( serviceRegistry, properties ),
sessionFactory.getServiceRegistry().getService(NativeQueryInterpreter.class) serviceRegistry.getService(NativeQueryInterpreter.class),
sqmCreationContext,
options,
options.getUuid(),
name
); );
} }
private static SqmFunctionRegistry createFunctionRegistry( private static SqmFunctionRegistry createFunctionRegistry(
SessionFactoryImplementor sessionFactory, ServiceRegistry serviceRegistry,
MetadataImplementor metadata, MetadataImplementor metadata,
QueryEngineOptions queryEngineOptions, QueryEngineOptions queryEngineOptions,
Dialect dialect) { Dialect dialect) {
@ -84,21 +91,17 @@ public class QueryEngineImpl implements QueryEngine {
} }
//TODO: probably better to turn this back into an anonymous class //TODO: probably better to turn this back into an anonymous class
final FunctionContributions functionContributions = new QueryEngineImpl.FunctionContributionsImpl( final FunctionContributions functionContributions =
sessionFactory.getServiceRegistry(), new FunctionContributionsImpl( serviceRegistry, metadata.getTypeConfiguration(), sqmFunctionRegistry );
metadata.getTypeConfiguration(), for ( FunctionContributor contributor : sortedFunctionContributors( serviceRegistry ) ) {
sqmFunctionRegistry
);
for ( FunctionContributor contributor : sortedFunctionContributors( sessionFactory.getServiceRegistry() ) ) {
contributor.contributeFunctions( functionContributions ); contributor.contributeFunctions( functionContributions );
} }
dialect.initializeFunctionRegistry( functionContributions ); dialect.initializeFunctionRegistry( functionContributions );
if ( LOG_HQL_FUNCTIONS.isDebugEnabled() ) { if ( LOG_HQL_FUNCTIONS.isDebugEnabled() ) {
sqmFunctionRegistry.getFunctionsByName().forEach( sqmFunctionRegistry.getFunctionsByName()
entry -> LOG_HQL_FUNCTIONS.debug( entry.getValue().getSignature( entry.getKey() ) ) .forEach( entry -> LOG_HQL_FUNCTIONS.debug( entry.getValue().getSignature( entry.getKey() ) ) );
);
} }
return sqmFunctionRegistry; return sqmFunctionRegistry;
@ -114,14 +117,16 @@ public class QueryEngineImpl implements QueryEngine {
private final SqmFunctionRegistry sqmFunctionRegistry; private final SqmFunctionRegistry sqmFunctionRegistry;
private QueryEngineImpl( private QueryEngineImpl(
SessionFactoryImplementor sessionFactory,
TypeConfiguration typeConfiguration, TypeConfiguration typeConfiguration,
HqlTranslator hqlTranslator, HqlTranslator hqlTranslator,
SqmTranslatorFactory sqmTranslatorFactory, SqmTranslatorFactory sqmTranslatorFactory,
SqmFunctionRegistry functionRegistry, SqmFunctionRegistry functionRegistry,
NamedObjectRepository namedObjectRepository, NamedObjectRepository namedObjectRepository,
QueryInterpretationCache interpretationCache, QueryInterpretationCache interpretationCache,
NativeQueryInterpreter nativeQueryInterpreter) { NativeQueryInterpreter nativeQueryInterpreter,
BindingContext context,
QueryEngineOptions options,
String uuid, String name) {
this.typeConfiguration = typeConfiguration; this.typeConfiguration = typeConfiguration;
this.sqmFunctionRegistry = functionRegistry; this.sqmFunctionRegistry = functionRegistry;
this.sqmTranslatorFactory = sqmTranslatorFactory; this.sqmTranslatorFactory = sqmTranslatorFactory;
@ -129,15 +134,13 @@ public class QueryEngineImpl implements QueryEngine {
this.namedObjectRepository = namedObjectRepository; this.namedObjectRepository = namedObjectRepository;
this.interpretationCache = interpretationCache; this.interpretationCache = interpretationCache;
this.nativeQueryInterpreter = nativeQueryInterpreter; this.nativeQueryInterpreter = nativeQueryInterpreter;
final SessionFactoryOptions sessionFactoryOptions = sessionFactory.getSessionFactoryOptions(); this.criteriaBuilder = createCriteriaBuilder( context, options, uuid, name );
this.criteriaBuilder = new SqmCriteriaNodeBuilder( }
sessionFactory.getUuid(),
sessionFactory.getName(), private SqmCriteriaNodeBuilder createCriteriaBuilder(
this, BindingContext context, QueryEngineOptions options,
sessionFactoryOptions.getJpaCompliance().isJpaQueryComplianceEnabled(), String uuid, String name) {
sessionFactoryOptions.getCriteriaValueHandlingMode(), return new SqmCriteriaNodeBuilder( uuid, name, this, options, context );
() -> sessionFactory
);
} }
private static HqlTranslator resolveHqlTranslator( private static HqlTranslator resolveHqlTranslator(
@ -171,10 +174,10 @@ public class QueryEngineImpl implements QueryEngine {
} }
private static List<FunctionContributor> sortedFunctionContributors(ServiceRegistry serviceRegistry) { private static List<FunctionContributor> sortedFunctionContributors(ServiceRegistry serviceRegistry) {
Collection<FunctionContributor> functionContributors = final Collection<FunctionContributor> functionContributors =
serviceRegistry.requireService(ClassLoaderService.class) serviceRegistry.requireService(ClassLoaderService.class)
.loadJavaServices(FunctionContributor.class); .loadJavaServices(FunctionContributor.class);
List<FunctionContributor> contributors = new ArrayList<>( functionContributors ); final List<FunctionContributor> contributors = new ArrayList<>( functionContributors );
contributors.sort( contributors.sort(
comparingInt( FunctionContributor::ordinal ) comparingInt( FunctionContributor::ordinal )
.thenComparing( a -> a.getClass().getCanonicalName() ) .thenComparing( a -> a.getClass().getCanonicalName() )
@ -183,8 +186,7 @@ public class QueryEngineImpl implements QueryEngine {
} }
private static QueryInterpretationCache buildInterpretationCache( private static QueryInterpretationCache buildInterpretationCache(
Supplier<StatisticsImplementor> statisticsSupplier, ServiceRegistry serviceRegistry, Map<String, Object> properties) {
Map<String, Object> properties) {
final boolean explicitUseCache = ConfigurationHelper.getBoolean( final boolean explicitUseCache = ConfigurationHelper.getBoolean(
AvailableSettings.QUERY_PLAN_CACHE_ENABLED, AvailableSettings.QUERY_PLAN_CACHE_ENABLED,
properties, properties,
@ -202,11 +204,11 @@ public class QueryEngineImpl implements QueryEngine {
? explicitMaxPlanSize ? explicitMaxPlanSize
: QueryEngine.DEFAULT_QUERY_PLAN_MAX_COUNT; : QueryEngine.DEFAULT_QUERY_PLAN_MAX_COUNT;
return new QueryInterpretationCacheStandardImpl( size, statisticsSupplier ); return new QueryInterpretationCacheStandardImpl( size, serviceRegistry );
} }
else { else {
// disabled // disabled
return new QueryInterpretationCacheDisabledImpl( statisticsSupplier ); return new QueryInterpretationCacheDisabledImpl( serviceRegistry );
} }
} }
@ -299,5 +301,4 @@ public class QueryEngineImpl implements QueryEngine {
return serviceRegistry; return serviceRegistry;
} }
} }
} }

View File

@ -20,6 +20,7 @@ import org.hibernate.query.sql.spi.ParameterInterpretation;
import org.hibernate.query.sqm.internal.DomainParameterXref; import org.hibernate.query.sqm.internal.DomainParameterXref;
import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement; import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.stat.spi.StatisticsImplementor;
/** /**
@ -27,10 +28,12 @@ import org.hibernate.stat.spi.StatisticsImplementor;
*/ */
public class QueryInterpretationCacheDisabledImpl implements QueryInterpretationCache { public class QueryInterpretationCacheDisabledImpl implements QueryInterpretationCache {
private final Supplier<StatisticsImplementor> statisticsSupplier; private final ServiceRegistry serviceRegistry;
public QueryInterpretationCacheDisabledImpl(Supplier<StatisticsImplementor> statisticsSupplier) { private StatisticsImplementor statistics;
this.statisticsSupplier = statisticsSupplier;
public QueryInterpretationCacheDisabledImpl(ServiceRegistry serviceRegistry) {
this.serviceRegistry = serviceRegistry;
} }
@Override @Override
@ -43,9 +46,16 @@ public class QueryInterpretationCacheDisabledImpl implements QueryInterpretation
return 0; return 0;
} }
private StatisticsImplementor getStatistics() {
if ( statistics == null ) {
statistics = serviceRegistry.requireService( StatisticsImplementor.class );
}
return statistics;
}
@Override @Override
public <R> SelectQueryPlan<R> resolveSelectQueryPlan(Key key, Supplier<SelectQueryPlan<R>> creator) { public <R> SelectQueryPlan<R> resolveSelectQueryPlan(Key key, Supplier<SelectQueryPlan<R>> creator) {
final StatisticsImplementor statistics = statisticsSupplier.get(); final StatisticsImplementor statistics = getStatistics();
if ( statistics.isStatisticsEnabled() ) { if ( statistics.isStatisticsEnabled() ) {
statistics.queryPlanCacheMiss( key.getQueryString() ); statistics.queryPlanCacheMiss( key.getQueryString() );
} }
@ -64,7 +74,7 @@ public class QueryInterpretationCacheDisabledImpl implements QueryInterpretation
@Override @Override
public <R> HqlInterpretation<R> resolveHqlInterpretation( public <R> HqlInterpretation<R> resolveHqlInterpretation(
String queryString, Class<R> expectedResultType, HqlTranslator translator) { String queryString, Class<R> expectedResultType, HqlTranslator translator) {
final StatisticsImplementor statistics = statisticsSupplier.get(); final StatisticsImplementor statistics = getStatistics();
final boolean stats = statistics.isStatisticsEnabled(); final boolean stats = statistics.isStatisticsEnabled();
final long startTime = stats ? System.nanoTime() : 0L; final long startTime = stats ? System.nanoTime() : 0L;

View File

@ -23,6 +23,7 @@ import org.hibernate.query.spi.SimpleHqlInterpretationImpl;
import org.hibernate.query.sql.spi.ParameterInterpretation; import org.hibernate.query.sql.spi.ParameterInterpretation;
import org.hibernate.query.sqm.internal.DomainParameterXref; import org.hibernate.query.sqm.internal.DomainParameterXref;
import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.stat.spi.StatisticsImplementor;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -40,17 +41,19 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation
*/ */
private final BoundedConcurrentHashMap<Key, QueryPlan> queryPlanCache; private final BoundedConcurrentHashMap<Key, QueryPlan> queryPlanCache;
private final ServiceRegistry serviceRegistry;
private final BoundedConcurrentHashMap<Object, HqlInterpretation<?>> hqlInterpretationCache; private final BoundedConcurrentHashMap<Object, HqlInterpretation<?>> hqlInterpretationCache;
private final BoundedConcurrentHashMap<String, ParameterInterpretation> nativeQueryParamCache; private final BoundedConcurrentHashMap<String, ParameterInterpretation> nativeQueryParamCache;
private final Supplier<StatisticsImplementor> statisticsSupplier;
public QueryInterpretationCacheStandardImpl(int maxQueryPlanCount, Supplier<StatisticsImplementor> statisticsSupplier) { private StatisticsImplementor statistics;
public QueryInterpretationCacheStandardImpl(int maxQueryPlanCount, ServiceRegistry serviceRegistry) {
log.debugf( "Starting QueryInterpretationCache(%s)", maxQueryPlanCount ); log.debugf( "Starting QueryInterpretationCache(%s)", maxQueryPlanCount );
this.queryPlanCache = new BoundedConcurrentHashMap<>( maxQueryPlanCount, 20, BoundedConcurrentHashMap.Eviction.LIRS ); this.queryPlanCache = new BoundedConcurrentHashMap<>( maxQueryPlanCount, 20, BoundedConcurrentHashMap.Eviction.LIRS );
this.hqlInterpretationCache = 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.nativeQueryParamCache = new BoundedConcurrentHashMap<>( maxQueryPlanCount, 20, BoundedConcurrentHashMap.Eviction.LIRS );
this.statisticsSupplier = statisticsSupplier; this.serviceRegistry = serviceRegistry;
} }
@Override @Override
@ -63,12 +66,19 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation
return queryPlanCache.size(); return queryPlanCache.size();
} }
private StatisticsImplementor getStatistics() {
if ( statistics == null ) {
statistics = serviceRegistry.requireService( StatisticsImplementor.class );
}
return statistics;
}
@Override @Override
public <R> SelectQueryPlan<R> resolveSelectQueryPlan( public <R> SelectQueryPlan<R> resolveSelectQueryPlan(
Key key, Key key,
Supplier<SelectQueryPlan<R>> creator) { Supplier<SelectQueryPlan<R>> creator) {
log.tracef( "QueryPlan#getSelectQueryPlan(%s)", key ); log.tracef( "QueryPlan#getSelectQueryPlan(%s)", key );
final StatisticsImplementor statistics = statisticsSupplier.get(); final StatisticsImplementor statistics = getStatistics();
final boolean stats = statistics.isStatisticsEnabled(); final boolean stats = statistics.isStatisticsEnabled();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -105,7 +115,7 @@ public class QueryInterpretationCacheStandardImpl implements QueryInterpretation
Class<R> expectedResultType, Class<R> expectedResultType,
HqlTranslator translator) { HqlTranslator translator) {
log.tracef( "QueryPlan#resolveHqlInterpretation( `%s` )", queryString ); log.tracef( "QueryPlan#resolveHqlInterpretation( `%s` )", queryString );
final StatisticsImplementor statistics = statisticsSupplier.get(); final StatisticsImplementor statistics = getStatistics();
final Object cacheKey = expectedResultType != null final Object cacheKey = expectedResultType != null
? new HqlInterpretationCacheKey( queryString, expectedResultType ) ? new HqlInterpretationCacheKey( queryString, expectedResultType )

View File

@ -9,6 +9,7 @@ package org.hibernate.query.spi;
import java.util.Map; import java.util.Map;
import org.hibernate.jpa.spi.JpaCompliance; import org.hibernate.jpa.spi.JpaCompliance;
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
import org.hibernate.query.criteria.ValueHandlingMode; import org.hibernate.query.criteria.ValueHandlingMode;
import org.hibernate.query.hql.HqlTranslator; import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor; import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
@ -73,9 +74,16 @@ public interface QueryEngineOptions {
ValueHandlingMode getCriteriaValueHandlingMode(); ValueHandlingMode getCriteriaValueHandlingMode();
default ImmutableEntityUpdateQueryHandlingMode getImmutableEntityUpdateQueryHandlingMode() {
return ImmutableEntityUpdateQueryHandlingMode.WARNING;
}
/** /**
* @see org.hibernate.cfg.AvailableSettings#PORTABLE_INTEGER_DIVISION * @see org.hibernate.cfg.AvailableSettings#PORTABLE_INTEGER_DIVISION
*/ */
boolean isPortableIntegerDivisionEnabled(); boolean isPortableIntegerDivisionEnabled();
String getSessionFactoryName();
String getUuid();
} }

View File

@ -10,9 +10,9 @@ import java.util.Calendar;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.BindableType; import org.hibernate.query.BindableType;
import org.hibernate.query.QueryArgumentException; import org.hibernate.query.QueryArgumentException;
import org.hibernate.query.BindingContext;
import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
@ -28,22 +28,22 @@ public class QueryParameterBindingValidator {
private QueryParameterBindingValidator() { private QueryParameterBindingValidator() {
} }
public void validate(BindableType<?> paramType, Object bind, SessionFactoryImplementor sessionFactory) { public void validate(BindableType<?> paramType, Object bind, BindingContext bindingContext) {
validate( paramType, bind, null, sessionFactory ); validate( paramType, bind, null, bindingContext);
} }
public void validate( public void validate(
BindableType<?> paramType, BindableType<?> paramType,
Object bind, Object bind,
TemporalType temporalPrecision, TemporalType temporalPrecision,
SessionFactoryImplementor sessionFactory) { BindingContext bindingContext) {
if ( bind == null || paramType == null ) { if ( bind == null || paramType == null ) {
// nothing we can check // nothing we can check
return; return;
} }
final Class<?> parameterJavaType; final Class<?> parameterJavaType;
final SqmExpressible<?> sqmExpressible = paramType.resolveExpressible( sessionFactory ); final SqmExpressible<?> sqmExpressible = paramType.resolveExpressible(bindingContext);
if ( paramType.getBindableJavaType() != null ) { if ( paramType.getBindableJavaType() != null ) {
parameterJavaType = paramType.getBindableJavaType(); parameterJavaType = paramType.getBindableJavaType();
} }

View File

@ -17,9 +17,11 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; 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.metamodel.model.domain.JpaMetamodel;
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
import org.hibernate.query.NullPrecedence; import org.hibernate.query.NullPrecedence;
import org.hibernate.query.BindingContext;
import org.hibernate.query.SortDirection; import org.hibernate.query.SortDirection;
import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.query.criteria.HibernateCriteriaBuilder;
import org.hibernate.query.criteria.JpaCoalesce; import org.hibernate.query.criteria.JpaCoalesce;
@ -78,7 +80,7 @@ import jakarta.persistence.criteria.Subquery;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public interface NodeBuilder extends HibernateCriteriaBuilder { public interface NodeBuilder extends HibernateCriteriaBuilder, BindingContext {
JpaMetamodel getDomainModel(); JpaMetamodel getDomainModel();
TypeConfiguration getTypeConfiguration(); TypeConfiguration getTypeConfiguration();
@ -1194,5 +1196,7 @@ public interface NodeBuilder extends HibernateCriteriaBuilder {
BasicType<Character> getCharacterType(); BasicType<Character> getCharacterType();
SessionFactoryImplementor getSessionFactory(); JpaCompliance getJpaCompliance();
ImmutableEntityUpdateQueryHandlingMode getImmutableEntityUpdateQueryHandlingMode();
} }

View File

@ -6,9 +6,9 @@
*/ */
package org.hibernate.query.sqm; package org.hibernate.query.sqm;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.query.BindableType; import org.hibernate.query.BindableType;
import org.hibernate.query.BindingContext;
import org.hibernate.query.sqm.tree.expression.SqmExpression; import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
@ -36,7 +36,7 @@ public interface SqmExpressible<J> extends BindableType<J> {
} }
@Override @Override
default SqmExpressible<J> resolveExpressible(SessionFactoryImplementor sessionFactory) { default SqmExpressible<J> resolveExpressible(BindingContext bindingContext) {
return this; return this;
} }

View File

@ -7,6 +7,7 @@
package org.hibernate.query.sqm.internal; package org.hibernate.query.sqm.internal;
import java.io.InvalidObjectException; import java.io.InvalidObjectException;
import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
@ -31,18 +32,17 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
import org.hibernate.dialect.function.AvgFunction; import org.hibernate.dialect.function.AvgFunction;
import org.hibernate.dialect.function.SumReturnTypeResolver; import org.hibernate.dialect.function.SumReturnTypeResolver;
import org.hibernate.dialect.function.array.DdlTypeHelper; import org.hibernate.dialect.function.array.DdlTypeHelper;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.SessionFactoryRegistry; import org.hibernate.internal.SessionFactoryRegistry;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper; 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.DomainType;
import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.model.domain.JpaMetamodel;
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; 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.model.domain.spi.JpaMetamodelImplementor;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.query.BindableType; import org.hibernate.query.BindableType;
import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode;
import org.hibernate.query.NullPrecedence; import org.hibernate.query.NullPrecedence;
import org.hibernate.query.BindingContext;
import org.hibernate.query.ReturnableType; import org.hibernate.query.ReturnableType;
import org.hibernate.query.SemanticException; import org.hibernate.query.SemanticException;
import org.hibernate.query.SortDirection; 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.ValueHandlingMode;
import org.hibernate.query.criteria.spi.CriteriaBuilderExtension; import org.hibernate.query.criteria.spi.CriteriaBuilderExtension;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryEngineOptions;
import org.hibernate.query.sqm.BinaryArithmeticOperator; import org.hibernate.query.sqm.BinaryArithmeticOperator;
import org.hibernate.query.sqm.ComparisonOperator; import org.hibernate.query.sqm.ComparisonOperator;
import org.hibernate.query.sqm.FrameKind; import org.hibernate.query.sqm.FrameKind;
@ -205,10 +208,11 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
private final String uuid; private final String uuid;
private final String name; private final String name;
private final transient boolean jpaComplianceEnabled; private final transient JpaCompliance jpaCompliance;
private final transient QueryEngine queryEngine; private final transient QueryEngine queryEngine;
private final transient Supplier<SessionFactoryImplementor> sessionFactory;
private transient ValueHandlingMode criteriaValueHandlingMode; private transient ValueHandlingMode criteriaValueHandlingMode;
private final transient ImmutableEntityUpdateQueryHandlingMode immutableEntityUpdateQueryHandlingMode;
private final transient BindingContext bindingContext;
private transient BasicType<Boolean> booleanType; private transient BasicType<Boolean> booleanType;
private transient BasicType<Integer> integerType; private transient BasicType<Integer> integerType;
private transient BasicType<Long> longType; private transient BasicType<Long> longType;
@ -220,15 +224,15 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
public SqmCriteriaNodeBuilder( public SqmCriteriaNodeBuilder(
String uuid, String name, String uuid, String name,
QueryEngine queryEngine, QueryEngine queryEngine,
boolean jpaComplianceEnabled, QueryEngineOptions options,
ValueHandlingMode criteriaValueHandlingMode, BindingContext bindingContext) {
Supplier<SessionFactoryImplementor> sessionFactory) {
this.sessionFactory = sessionFactory;
this.queryEngine = queryEngine; this.queryEngine = queryEngine;
this.uuid = uuid; this.uuid = uuid;
this.name = name; this.name = name;
this.jpaComplianceEnabled = jpaComplianceEnabled; this.jpaCompliance = options.getJpaCompliance();
this.criteriaValueHandlingMode = criteriaValueHandlingMode; this.criteriaValueHandlingMode = options.getCriteriaValueHandlingMode();
this.immutableEntityUpdateQueryHandlingMode = options.getImmutableEntityUpdateQueryHandlingMode();
this.bindingContext = bindingContext;
// load registered criteria builder extensions // load registered criteria builder extensions
this.extensions = new HashMap<>(); this.extensions = new HashMap<>();
for ( CriteriaBuilderExtension extension : ServiceLoader.load( CriteriaBuilderExtension.class ) ) { for ( CriteriaBuilderExtension extension : ServiceLoader.load( CriteriaBuilderExtension.class ) ) {
@ -243,7 +247,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
@Override @Override
public JpaMetamodel getDomainModel() { public JpaMetamodel getDomainModel() {
return getSessionFactory().getJpaMetamodel(); return bindingContext.getJpaMetamodel();
} }
@Override @Override
@ -253,14 +257,18 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
@Override @Override
public boolean isJpaQueryComplianceEnabled() { public boolean isJpaQueryComplianceEnabled() {
return jpaComplianceEnabled; return jpaCompliance.isJpaQueryComplianceEnabled();
} }
@Override @Override
public SessionFactoryImplementor getSessionFactory() { public JpaCompliance getJpaCompliance() {
return sessionFactory.get(); return jpaCompliance;
} }
@Override
public ImmutableEntityUpdateQueryHandlingMode getImmutableEntityUpdateQueryHandlingMode() {
return immutableEntityUpdateQueryHandlingMode;
}
@Override @Override
public BasicType<Boolean> getBooleanType() { public BasicType<Boolean> getBooleanType() {
@ -329,7 +337,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
@Override @Override
public JpaMetamodelImplementor getJpaMetamodel() { public JpaMetamodelImplementor getJpaMetamodel() {
return getSessionFactory().getJpaMetamodel(); return (JpaMetamodelImplementor) bindingContext.getJpaMetamodel();
} }
@Override @Override
@ -349,8 +357,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
@Override @Override
public <T> SqmSelectStatement<T> createQuery(String hql, Class<T> resultClass) { public <T> SqmSelectStatement<T> createQuery(String hql, Class<T> resultClass) {
final SqmStatement<T> statement = final SqmStatement<T> statement =
sessionFactory.get().getQueryEngine().getHqlTranslator() queryEngine.getHqlTranslator().translate( hql, resultClass );
.translate( hql, resultClass );
if ( statement instanceof SqmSelectStatement ) { if ( statement instanceof SqmSelectStatement ) {
return new SqmSelectStatement<>( (SqmSelectStatement<T>) statement ); return new SqmSelectStatement<>( (SqmSelectStatement<T>) statement );
} }
@ -1545,7 +1552,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
@Override @Override
public <T> SqmLiteral<T> literal(T value) { public <T> SqmLiteral<T> literal(T value) {
if ( value == null ) { if ( value == null ) {
if ( jpaComplianceEnabled ) { if ( jpaCompliance.isJpaQueryComplianceEnabled() ) {
throw new IllegalArgumentException( "literal value cannot be null" ); throw new IllegalArgumentException( "literal value cannot be null" );
} }
return new SqmLiteralNull<>( this ); return new SqmLiteralNull<>( this );
@ -1553,13 +1560,14 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
else { else {
final BindableType<? super T> valueParamType = getParameterBindType( value ); final BindableType<? super T> valueParamType = getParameterBindType( value );
final SqmExpressible<? super T> sqmExpressible = final SqmExpressible<? super T> sqmExpressible =
valueParamType == null ? null : valueParamType.resolveExpressible( getSessionFactory() ); valueParamType == null ? null : valueParamType.resolveExpressible( this );
return new SqmLiteral<>( value, sqmExpressible, this ); return new SqmLiteral<>( value, sqmExpressible, this );
} }
} }
private MappingMetamodelImplementor getMappingMetamodel() { @Override
return getSessionFactory().getMappingMetamodel(); public MappingMetamodelImplementor getMappingMetamodel() {
return (MappingMetamodelImplementor) bindingContext.getMappingMetamodel();
} }
@Override @Override
@ -2086,7 +2094,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
} }
else { else {
return bindableType.getBindableJavaType().isInstance( value ) 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 ); return new ValueBindJpaCriteriaParameter<>( bindableType, value, this );
} }
final T coercedValue = final T coercedValue =
bindableType.resolveExpressible( getSessionFactory() ).getExpressibleJavaType() bindableType.resolveExpressible( this ).getExpressibleJavaType()
.coerce(value, this::getTypeConfiguration ); .coerce(value, this::getTypeConfiguration );
if ( isInstance( bindableType, coercedValue ) ) { if ( isInstance( bindableType, coercedValue ) ) {
return new ValueBindJpaCriteriaParameter<>( bindableType, coercedValue, this ); return new ValueBindJpaCriteriaParameter<>( bindableType, coercedValue, this );
@ -2151,7 +2159,7 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
} }
DomainType<E> elementType = null; DomainType<E> elementType = null;
if ( bindableType != null ) { if ( bindableType != null ) {
final SqmExpressible<E> sqmExpressible = bindableType.resolveExpressible( getSessionFactory() ); final SqmExpressible<E> sqmExpressible = bindableType.resolveExpressible( this );
elementType = sqmExpressible.getSqmType(); elementType = sqmExpressible.getSqmType();
} }
if ( elementType == null ) { 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. * @throws InvalidObjectException Thrown if we could not resolve the factory by uuid/name.
*/ */
@Serial
private Object readResolve() throws InvalidObjectException { private Object readResolve() throws InvalidObjectException {
LOG.trace( "Resolving serialized SqmCriteriaNodeBuilder" ); LOG.trace( "Resolving serialized SqmCriteriaNodeBuilder" );
return locateSessionFactoryOnDeserialization( uuid, name ).getCriteriaBuilder(); return locateSessionFactoryOnDeserialization( uuid, name ).getCriteriaBuilder();

View File

@ -24,6 +24,7 @@ import java.util.function.Function;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.jpa.spi.JpaCompliance;
import org.hibernate.metamodel.MappingMetamodel; import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.metamodel.mapping.BasicValuedMapping; import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.Bindable; import org.hibernate.metamodel.mapping.Bindable;
@ -307,17 +308,15 @@ public class SqmUtil {
} while (declaringType.getPersistenceType() != Type.PersistenceType.ENTITY ); } while (declaringType.getPersistenceType() != Type.PersistenceType.ENTITY );
pathBuilder.insert(0, '.'); pathBuilder.insert(0, '.');
pathBuilder.insert( 0, attribute.getName() ); pathBuilder.insert( 0, attribute.getName() );
final EntityPersister entityDescriptor = sqmJoin.nodeBuilder() final EntityPersister entityDescriptor =
.getSessionFactory() sqmJoin.nodeBuilder().getMappingMetamodel()
.getMappingMetamodel() .getEntityDescriptor( ( (EntityDomainType<?>) declaringType ).getHibernateEntityName() );
.getEntityDescriptor( ( (EntityDomainType<?>) declaringType ).getHibernateEntityName() );
return (EntityAssociationMapping) entityDescriptor.findByPath( pathBuilder.toString() ); return (EntityAssociationMapping) entityDescriptor.findByPath( pathBuilder.toString() );
} }
else { else {
final EntityPersister entityDescriptor = sqmJoin.nodeBuilder() final EntityPersister entityDescriptor =
.getSessionFactory() sqmJoin.nodeBuilder().getMappingMetamodel()
.getMappingMetamodel() .getEntityDescriptor( ( (EntityDomainType<?>) declaringType ).getHibernateEntityName() );
.getEntityDescriptor( ( (EntityDomainType<?>) declaringType ).getHibernateEntityName() );
return (EntityAssociationMapping) entityDescriptor.findAttributeMapping( attribute.getName() ); return (EntityAssociationMapping) entityDescriptor.findAttributeMapping( attribute.getName() );
} }
} }
@ -999,7 +998,7 @@ public class SqmUtil {
} }
private static void checkQueryReturnType(SqmQuerySpec<?> querySpec, Class<?> expectedResultClass) { private static void checkQueryReturnType(SqmQuerySpec<?> querySpec, Class<?> expectedResultClass) {
final SessionFactoryImplementor sessionFactory = querySpec.nodeBuilder().getSessionFactory(); final JpaCompliance jpaCompliance = querySpec.nodeBuilder().getJpaCompliance();
final List<SqmSelection<?>> selections = querySpec.getSelectClause().getSelections(); final List<SqmSelection<?>> selections = querySpec.getSelectClause().getSelections();
if ( selections == null || selections.isEmpty() ) { if ( selections == null || selections.isEmpty() ) {
// make sure there is at least one root // 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 there is a single root, use that as the selection
if ( sqmRoots.size() == 1 ) { if ( sqmRoots.size() == 1 ) {
verifySingularSelectionType( expectedResultClass, sessionFactory, sqmRoots.get( 0 ) ); verifySingularSelectionType( expectedResultClass, jpaCompliance, sqmRoots.get( 0 ) );
} }
else { else {
throw new IllegalArgumentException( "Criteria has multiple query roots" ); throw new IllegalArgumentException( "Criteria has multiple query roots" );
@ -1023,17 +1022,17 @@ public class SqmUtil {
? expectedResultClass.getComponentType() ? expectedResultClass.getComponentType()
: expectedResultClass; : expectedResultClass;
for ( JpaSelection<?> selection : selectableNode.getSelectionItems() ) { for ( JpaSelection<?> selection : selectableNode.getSelectionItems() ) {
verifySelectionType( expectedSelectItemType, sessionFactory, (SqmSelectableNode<?>) selection ); verifySelectionType( expectedSelectItemType, jpaCompliance, (SqmSelectableNode<?>) selection );
} }
} }
else { else {
verifySingularSelectionType( expectedResultClass, sessionFactory, sqmSelection.getSelectableNode() ); verifySingularSelectionType( expectedResultClass, jpaCompliance, sqmSelection.getSelectableNode() );
} }
} }
else if ( expectedResultClass.isArray() ) { else if ( expectedResultClass.isArray() ) {
final Class<?> componentType = expectedResultClass.getComponentType(); final Class<?> componentType = expectedResultClass.getComponentType();
for ( SqmSelection<?> selection : selections ) { 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( private static void verifySingularSelectionType(
Class<?> expectedResultClass, Class<?> expectedResultClass,
SessionFactoryImplementor sessionFactory, JpaCompliance jpaCompliance,
SqmSelectableNode<?> selectableNode) { SqmSelectableNode<?> selectableNode) {
try { try {
verifySelectionType( expectedResultClass, sessionFactory, selectableNode ); verifySelectionType( expectedResultClass, jpaCompliance, selectableNode );
} }
catch (QueryTypeMismatchException mismatchException) { catch (QueryTypeMismatchException mismatchException) {
// Check for special case of a single selection item and implicit instantiation. // Check for special case of a single selection item and implicit instantiation.
@ -1084,7 +1083,7 @@ public class SqmUtil {
private static <T> void verifySelectionType( private static <T> void verifySelectionType(
Class<T> expectedResultClass, Class<T> expectedResultClass,
SessionFactoryImplementor sessionFactory, JpaCompliance jpaCompliance,
SqmSelectableNode<?> selection) { SqmSelectableNode<?> selection) {
// special case for parameters in the select list // special case for parameters in the select list
if ( selection instanceof SqmParameter ) { if ( selection instanceof SqmParameter ) {
@ -1097,18 +1096,18 @@ public class SqmUtil {
} }
} }
if ( !sessionFactory.getSessionFactoryOptions().getJpaCompliance().isJpaQueryComplianceEnabled() ) { if ( !jpaCompliance.isJpaQueryComplianceEnabled() ) {
verifyResultType( expectedResultClass, selection.getExpressible() ); verifyResultType( expectedResultClass, selection.getExpressible() );
} }
} }
public static boolean isResultTypeAlwaysAllowed(Class<?> expectedResultClass) { public static boolean isResultTypeAlwaysAllowed(Class<?> expectedResultClass) {
return expectedResultClass == null return expectedResultClass == null
|| expectedResultClass == Object.class || expectedResultClass == Object.class
|| expectedResultClass == Object[].class || expectedResultClass == Object[].class
|| expectedResultClass == List.class || expectedResultClass == List.class
|| expectedResultClass == Map.class || expectedResultClass == Map.class
|| expectedResultClass == Tuple.class; || expectedResultClass == Tuple.class;
} }
protected static void verifyResultType(Class<?> resultClass, @Nullable SqmExpressible<?> selectionExpressible) { protected static void verifyResultType(Class<?> resultClass, @Nullable SqmExpressible<?> selectionExpressible) {

View File

@ -8,7 +8,6 @@ package org.hibernate.query.sqm.internal;
import jakarta.persistence.criteria.Expression; import jakarta.persistence.criteria.Expression;
import jakarta.persistence.metamodel.EntityType; import jakarta.persistence.metamodel.EntityType;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.EmbeddableDomainType; 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.TupleType;
import org.hibernate.metamodel.model.domain.internal.EntityDiscriminatorSqmPathSource; import org.hibernate.metamodel.model.domain.internal.EntityDiscriminatorSqmPathSource;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.BindingContext;
import org.hibernate.query.SemanticException; import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.BinaryArithmeticOperator; import org.hibernate.query.sqm.BinaryArithmeticOperator;
import org.hibernate.query.sqm.SqmExpressible; 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.BasicPluralType;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.QueryParameterJavaObjectType; import org.hibernate.type.QueryParameterJavaObjectType;
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType;
import java.time.temporal.Temporal; 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 * function application) is legal only when the entity types belong to the same mapped
* entity hierarchy. * entity hierarchy.
* *
* @see #assertComparable(Expression, Expression, SessionFactoryImplementor) * @see #assertComparable(Expression, Expression, BindingContext)
* @see #assertAssignable(String, SqmPath, SqmTypedNode, SessionFactoryImplementor) * @see #assertAssignable(String, SqmPath, SqmTypedNode, BindingContext)
* *
* @author Gavin King * @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 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 * @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( public static boolean areTypesComparable(
SqmExpressible<?> lhsType, SqmExpressible<?> lhsType,
SqmExpressible<?> rhsType, SqmExpressible<?> rhsType,
SessionFactoryImplementor factory) { BindingContext bindingContext) {
if ( lhsType == null || rhsType == null || lhsType == rhsType ) { if ( lhsType == null || rhsType == null || lhsType == rhsType ) {
return true; return true;
} }
@ -139,7 +138,7 @@ public class TypecheckUtil {
// for tuple constructors, we must check each element // for tuple constructors, we must check each element
if ( lhsDomainType instanceof TupleType && rhsDomainType instanceof TupleType ) { 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 // 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 // entities can be compared if they belong to the same inheritance hierarchy
if ( lhsDomainType instanceof EntityType && rhsDomainType instanceof EntityType ) { 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 // entities can be compared to discriminators if they belong to
// the same inheritance hierarchy // the same inheritance hierarchy
if ( lhsDomainType instanceof EntityDiscriminatorSqmPathSource ) { if ( lhsDomainType instanceof EntityDiscriminatorSqmPathSource ) {
return isDiscriminatorTypeComparable( (EntityDiscriminatorSqmPathSource<?>) lhsDomainType, rhsDomainType, factory ); return isDiscriminatorTypeComparable( (EntityDiscriminatorSqmPathSource<?>) lhsDomainType, rhsDomainType, bindingContext);
} }
if ( rhsDomainType instanceof EntityDiscriminatorSqmPathSource ) { 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 // Treat the expressions as comparable if they belong to the same
@ -173,7 +172,7 @@ public class TypecheckUtil {
// enums, user-defined types, etc. // enums, user-defined types, etc.
if ( lhsDomainType instanceof JdbcMapping && rhsDomainType instanceof JdbcMapping ) { if ( lhsDomainType instanceof JdbcMapping && rhsDomainType instanceof JdbcMapping ) {
if ( areJdbcMappingsComparable( (JdbcMapping) lhsDomainType, (JdbcMapping) rhsDomainType, factory ) ) { if ( areJdbcMappingsComparable( (JdbcMapping) lhsDomainType, (JdbcMapping) rhsDomainType, bindingContext) ) {
return true; return true;
} }
} }
@ -195,14 +194,14 @@ public class TypecheckUtil {
private static boolean areJdbcMappingsComparable( private static boolean areJdbcMappingsComparable(
JdbcMapping lhsJdbcMapping, JdbcMapping lhsJdbcMapping,
JdbcMapping rhsJdbcMapping, JdbcMapping rhsJdbcMapping,
SessionFactoryImplementor factory) { BindingContext bindingContext) {
if ( areJdbcTypesComparable( lhsJdbcMapping.getJdbcType(), rhsJdbcMapping.getJdbcType() ) ) { if ( areJdbcTypesComparable( lhsJdbcMapping.getJdbcType(), rhsJdbcMapping.getJdbcType() ) ) {
return true; return true;
} }
// converters are implicitly applied to the other side when its domain type is compatible // converters are implicitly applied to the other side when its domain type is compatible
else if ( lhsJdbcMapping.getValueConverter() != null || rhsJdbcMapping.getValueConverter() != null ) { else if ( lhsJdbcMapping.getValueConverter() != null || rhsJdbcMapping.getValueConverter() != null ) {
final JdbcMapping lhsDomainMapping = getDomainJdbcType( lhsJdbcMapping, factory ); final JdbcMapping lhsDomainMapping = getDomainJdbcType( lhsJdbcMapping, bindingContext);
final JdbcMapping rhsDomainMapping = getDomainJdbcType( rhsJdbcMapping, factory ); final JdbcMapping rhsDomainMapping = getDomainJdbcType( rhsJdbcMapping, bindingContext);
return lhsDomainMapping != null && rhsDomainMapping != null && areJdbcTypesComparable( return lhsDomainMapping != null && rhsDomainMapping != null && areJdbcTypesComparable(
lhsDomainMapping.getJdbcType(), lhsDomainMapping.getJdbcType(),
rhsDomainMapping.getJdbcType() rhsDomainMapping.getJdbcType()
@ -220,11 +219,11 @@ public class TypecheckUtil {
|| lhsJdbcType.isNumber() && rhsJdbcType.isNumber(); || lhsJdbcType.isNumber() && rhsJdbcType.isNumber();
} }
private static JdbcMapping getDomainJdbcType(JdbcMapping jdbcMapping, SessionFactoryImplementor factory) { private static JdbcMapping getDomainJdbcType(JdbcMapping jdbcMapping, BindingContext bindingContext) {
if ( jdbcMapping.getValueConverter() != null ) { if ( jdbcMapping.getValueConverter() != null ) {
final BasicType<?> basicType = factory.getTypeConfiguration().getBasicTypeForJavaType( final BasicType<?> basicType =
jdbcMapping.getValueConverter().getDomainJavaType().getJavaType() bindingContext.getTypeConfiguration()
); .getBasicTypeForJavaType( jdbcMapping.getValueConverter().getDomainJavaType().getJavaType() );
if ( basicType != null ) { if ( basicType != null ) {
return basicType.getJdbcMapping(); return basicType.getJdbcMapping();
} }
@ -255,7 +254,7 @@ public class TypecheckUtil {
} }
private static boolean areTupleTypesComparable( private static boolean areTupleTypesComparable(
SessionFactoryImplementor factory, BindingContext bindingContext,
TupleType<?> lhsTuple, TupleType<?> lhsTuple,
TupleType<?> rhsTuple) { TupleType<?> rhsTuple) {
if ( rhsTuple.componentCount() != lhsTuple.componentCount() ) { if ( rhsTuple.componentCount() != lhsTuple.componentCount() ) {
@ -263,7 +262,7 @@ public class TypecheckUtil {
} }
else { else {
for ( int i = 0; i < lhsTuple.componentCount(); i++ ) { 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; return false;
} }
} }
@ -273,32 +272,32 @@ public class TypecheckUtil {
private static boolean areEntityTypesComparable( private static boolean areEntityTypesComparable(
EntityType<?> lhsType, EntityType<?> rhsType, EntityType<?> lhsType, EntityType<?> rhsType,
SessionFactoryImplementor factory) { BindingContext bindingContext) {
EntityPersister lhsEntity = getEntityDescriptor( factory, lhsType.getName() ); EntityPersister lhsEntity = getEntityDescriptor(bindingContext, lhsType.getName() );
EntityPersister rhsEntity = getEntityDescriptor( factory, rhsType.getName() ); EntityPersister rhsEntity = getEntityDescriptor(bindingContext, rhsType.getName() );
return lhsEntity.getRootEntityName().equals( rhsEntity.getRootEntityName() ); return lhsEntity.getRootEntityName().equals( rhsEntity.getRootEntityName() );
} }
private static boolean isDiscriminatorTypeComparable( private static boolean isDiscriminatorTypeComparable(
EntityDiscriminatorSqmPathSource<?> lhsDiscriminator, SqmExpressible<?> rhsType, EntityDiscriminatorSqmPathSource<?> lhsDiscriminator, SqmExpressible<?> rhsType,
SessionFactoryImplementor factory) { BindingContext bindingContext) {
String entityName = lhsDiscriminator.getEntityDomainType().getHibernateEntityName(); String entityName = lhsDiscriminator.getEntityDomainType().getHibernateEntityName();
EntityPersister lhsEntity = factory.getMappingMetamodel().getEntityDescriptor( entityName ); EntityPersister lhsEntity = bindingContext.getMappingMetamodel().getEntityDescriptor( entityName );
if ( rhsType instanceof EntityType ) { if ( rhsType instanceof EntityType ) {
String rhsEntityName = ((EntityType<?>) rhsType).getName(); String rhsEntityName = ((EntityType<?>) rhsType).getName();
EntityPersister rhsEntity = getEntityDescriptor( factory, rhsEntityName ); EntityPersister rhsEntity = getEntityDescriptor(bindingContext, rhsEntityName );
return lhsEntity.getRootEntityName().equals( rhsEntity.getRootEntityName() ); return lhsEntity.getRootEntityName().equals( rhsEntity.getRootEntityName() );
} }
else if ( rhsType instanceof EntityDiscriminatorSqmPathSource ) { else if ( rhsType instanceof EntityDiscriminatorSqmPathSource ) {
EntityDiscriminatorSqmPathSource<?> discriminator = (EntityDiscriminatorSqmPathSource<?>) rhsType; EntityDiscriminatorSqmPathSource<?> discriminator = (EntityDiscriminatorSqmPathSource<?>) rhsType;
String rhsEntityName = discriminator.getEntityDomainType().getHibernateEntityName(); String rhsEntityName = discriminator.getEntityDomainType().getHibernateEntityName();
EntityPersister rhsEntity = factory.getMappingMetamodel().getEntityDescriptor( rhsEntityName ); EntityPersister rhsEntity = bindingContext.getMappingMetamodel().getEntityDescriptor( rhsEntityName );
return rhsEntity.getRootEntityName().equals( lhsEntity.getRootEntityName() ); return rhsEntity.getRootEntityName().equals( lhsEntity.getRootEntityName() );
} }
else { else {
BasicType<?> discriminatorType = (BasicType<?>) BasicType<?> discriminatorType = (BasicType<?>)
lhsDiscriminator.getEntityMapping().getDiscriminatorMapping().getMappedType(); 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 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 * @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( private static boolean isTypeAssignable(
SqmPathSource<?> targetType, SqmExpressible<?> expressionType, SqmPathSource<?> targetType, SqmExpressible<?> expressionType,
SessionFactoryImplementor factory) { BindingContext bindingContext) {
if ( targetType == null || expressionType == null || targetType == expressionType ) { if ( targetType == null || expressionType == null || targetType == expressionType ) {
return true; return true;
@ -319,7 +318,7 @@ public class TypecheckUtil {
// entities can be assigned if they belong to the same inheritance hierarchy // entities can be assigned if they belong to the same inheritance hierarchy
if ( targetType instanceof EntityType && expressionType instanceof EntityType ) { 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 // Treat the expression as assignable to the target path if they belong
@ -367,21 +366,21 @@ public class TypecheckUtil {
private static boolean isEntityTypeAssignable( private static boolean isEntityTypeAssignable(
EntityType<?> lhsType, EntityType<?> rhsType, EntityType<?> lhsType, EntityType<?> rhsType,
SessionFactoryImplementor factory) { BindingContext bindingContext) {
EntityPersister lhsEntity = getEntityDescriptor( factory, lhsType.getName() ); EntityPersister lhsEntity = getEntityDescriptor(bindingContext, lhsType.getName() );
EntityPersister rhsEntity = getEntityDescriptor( factory, rhsType.getName() ); EntityPersister rhsEntity = getEntityDescriptor(bindingContext, rhsType.getName() );
return lhsEntity.isSubclassEntityName( rhsEntity.getEntityName() ); return lhsEntity.isSubclassEntityName( rhsEntity.getEntityName() );
} }
private static EntityPersister getEntityDescriptor(SessionFactoryImplementor factory, String name) { private static EntityPersister getEntityDescriptor(BindingContext bindingContext, String name) {
return factory.getMappingMetamodel() return bindingContext.getMappingMetamodel()
.getEntityDescriptor( factory.getJpaMetamodel().qualifyImportableName( name ) ); .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<?> left = (SqmExpression<?>) x;
final SqmExpression<?> right = (SqmExpression<?>) y; final SqmExpression<?> right = (SqmExpression<?>) y;
final Integer leftTupleLength = left.getTupleLength(); final Integer leftTupleLength = left.getTupleLength();
@ -401,7 +400,7 @@ public class TypecheckUtil {
if ( !( left instanceof SqmLiteralNull ) && !( right instanceof SqmLiteralNull ) ) { if ( !( left instanceof SqmLiteralNull ) && !( right instanceof SqmLiteralNull ) ) {
final SqmExpressible<?> leftType = left.getExpressible(); final SqmExpressible<?> leftType = left.getExpressible();
final SqmExpressible<?> rightType = right.getExpressible(); final SqmExpressible<?> rightType = right.getExpressible();
if ( !areTypesComparable( leftType, rightType, factory ) ) { if ( !areTypesComparable( leftType, rightType, bindingContext) ) {
throw new SemanticException( throw new SemanticException(
String.format( String.format(
"Cannot compare left expression of type '%s' with right expression of type '%s'", "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( public static void assertAssignable(
String hqlString, String hqlString,
SqmPath<?> targetPath, SqmTypedNode<?> expression, SqmPath<?> targetPath, SqmTypedNode<?> expression,
SessionFactoryImplementor factory) { BindingContext bindingContext) {
// allow assigning literal null to things // allow assigning literal null to things
if ( expression instanceof SqmLiteralNull ) { if ( expression instanceof SqmLiteralNull ) {
// TODO: check that the target path is nullable // TODO: check that the target path is nullable
@ -427,7 +426,7 @@ public class TypecheckUtil {
else { else {
SqmPathSource<?> targetType = targetPath.getNodeType(); SqmPathSource<?> targetType = targetPath.getNodeType();
SqmExpressible<?> expressionType = expression.getNodeType(); SqmExpressible<?> expressionType = expression.getNodeType();
if ( !isTypeAssignable( targetType, expressionType, factory ) ) { if ( !isTypeAssignable( targetType, expressionType, bindingContext) ) {
throw new SemanticException( throw new SemanticException(
String.format( String.format(
"Cannot assign expression of type '%s' to target path '%s' of type '%s'", "Cannot assign expression of type '%s' to target path '%s' of type '%s'",

View File

@ -8,6 +8,7 @@ package org.hibernate.query.sqm.spi;
import org.hibernate.Incubating; import org.hibernate.Incubating;
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
import org.hibernate.query.BindingContext;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
@ -19,7 +20,7 @@ import org.hibernate.type.spi.TypeConfiguration;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@Incubating @Incubating
public interface SqmCreationContext { public interface SqmCreationContext extends BindingContext {
/** /**
* Access to the domain model metadata * Access to the domain model metadata
*/ */

View File

@ -6162,7 +6162,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
} }
} }
final SqmExpressible<?> paramSqmType = paramType.resolveExpressible( creationContext.getSessionFactory() ); final SqmExpressible<?> paramSqmType = paramType.resolveExpressible( creationContext );
if ( paramSqmType instanceof SqmPath ) { if ( paramSqmType instanceof SqmPath ) {
final MappingModelExpressible<?> modelPart = determineValueMapping( (SqmPath<?>) paramSqmType ); final MappingModelExpressible<?> modelPart = determineValueMapping( (SqmPath<?>) paramSqmType );

View File

@ -196,7 +196,7 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public SqmPath<?> get(String attributeName) { public SqmPath<?> get(String attributeName) {
final SqmPathSource<?> subNavigable = final SqmPathSource<?> subNavigable =
getResolvedModel().getSubPathSource( attributeName, nodeBuilder().getSessionFactory().getJpaMetamodel() ); getResolvedModel().getSubPathSource( attributeName, nodeBuilder().getJpaMetamodel() );
return resolvePath( attributeName, subNavigable ); return resolvePath( attributeName, subNavigable );
} }

View File

@ -54,7 +54,7 @@ public class JpaCriteriaParameter<T>
if ( type == null ) { if ( type == null ) {
return null; return null;
} }
return type.resolveExpressible( nodeBuilder.getSessionFactory() ); return type.resolveExpressible( nodeBuilder );
} }
@Override @Override

View File

@ -15,9 +15,9 @@ import java.time.LocalDateTime;
import java.time.LocalTime; import java.time.LocalTime;
import java.time.OffsetTime; import java.time.OffsetTime;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.model.domain.internal.EmbeddedSqmPathSource; import org.hibernate.metamodel.model.domain.internal.EmbeddedSqmPathSource;
import org.hibernate.query.BindableType; import org.hibernate.query.BindableType;
import org.hibernate.query.BindingContext;
import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.BinaryArithmeticOperator; import org.hibernate.query.sqm.BinaryArithmeticOperator;
@ -37,26 +37,18 @@ import org.hibernate.usertype.internal.OffsetTimeCompositeUserType;
*/ */
public class SqmExpressionHelper { public class SqmExpressionHelper {
public static <T> SqmExpressible<T> toSqmType(BindableType<T> parameterType, SqmCreationState creationState) { public static <T> SqmExpressible<T> toSqmType(BindableType<T> parameterType, SqmCreationState creationState) {
return toSqmType( parameterType, creationState.getCreationContext().getNodeBuilder().getSessionFactory() ); return toSqmType( parameterType, creationState.getCreationContext() );
} }
public static <T> SqmExpressible<T> toSqmType(BindableType<T> anticipatedType, NodeBuilder nodeBuilder) { public static <T> SqmExpressible<T> toSqmType(
return toSqmType( anticipatedType, nodeBuilder.getSessionFactory() ); BindableType<T> anticipatedType, BindingContext bindingContext) {
}
// public static <T> SqmExpressible<T> toSqmType(BindableType<T> anticipatedType, TypeConfiguration typeConfiguration) {
// return toSqmType( anticipatedType, typeConfiguration.getSessionFactory() );
// }
public static <T> SqmExpressible<T> toSqmType(BindableType<T> anticipatedType, SessionFactoryImplementor sessionFactory) {
if ( anticipatedType == null ) { if ( anticipatedType == null ) {
return null; return null;
} }
final SqmExpressible<T> sqmExpressible = anticipatedType.resolveExpressible( sessionFactory ); final SqmExpressible<T> sqmExpressible = anticipatedType.resolveExpressible(bindingContext);
assert sqmExpressible != null; assert sqmExpressible != null;
return sqmExpressible; return sqmExpressible;
} }
public static SqmLiteral<Timestamp> timestampLiteralFrom(String literalText, SqmCreationState creationState) { public static SqmLiteral<Timestamp> timestampLiteralFrom(String literalText, SqmCreationState creationState) {

View File

@ -90,11 +90,11 @@ public abstract class AbstractSqmInsertStatement<T> extends AbstractSqmDmlStatem
null null
); );
} }
final SessionFactoryImplementor factory = nodeBuilder().getSessionFactory();
for ( int i = 0; i < expressionsSize; i++ ) { for ( int i = 0; i < expressionsSize; i++ ) {
final SqmTypedNode<?> expression = expressions.get( i ); final SqmTypedNode<?> expression = expressions.get( i );
final SqmPath<?> targetPath = insertionTargetPaths.get(i); final SqmPath<?> targetPath = insertionTargetPaths.get(i);
assertAssignable( null, targetPath, expression, factory ); assertAssignable( null, targetPath, expression, nodeBuilder() );
// if ( expression.getNodeJavaType() == null ) { // if ( expression.getNodeJavaType() == null ) {
// continue; // continue;
// } // }

View File

@ -83,7 +83,7 @@ public class SqmConflictUpdateAction<T> implements SqmNode, JpaConflictUpdateAct
else { else {
expression = (SqmExpression) nodeBuilder().value( value ); expression = (SqmExpression) nodeBuilder().value( value );
} }
assertAssignable( null, sqmPath, expression, nodeBuilder().getSessionFactory() ); assertAssignable( null, sqmPath, expression, nodeBuilder() );
applyAssignment( sqmPath, expression ); applyAssignment( sqmPath, expression );
return this; return this;
} }

View File

@ -34,8 +34,8 @@ public class SqmBetweenPredicate extends AbstractNegatableSqmPredicate {
this.lowerBound = lowerBound; this.lowerBound = lowerBound;
this.upperBound = upperBound; this.upperBound = upperBound;
assertComparable( expression, lowerBound, nodeBuilder.getSessionFactory() ); assertComparable( expression, lowerBound, nodeBuilder );
assertComparable( expression, upperBound, nodeBuilder.getSessionFactory() ); assertComparable( expression, upperBound, nodeBuilder );
final SqmExpressible<?> expressibleType = QueryHelper.highestPrecedenceType( final SqmExpressible<?> expressibleType = QueryHelper.highestPrecedenceType(
expression.getExpressible(), expression.getExpressible(),

View File

@ -43,7 +43,7 @@ public class SqmComparisonPredicate extends AbstractNegatableSqmPredicate {
this.rightHandExpression = rightHandExpression; this.rightHandExpression = rightHandExpression;
this.operator = operator; this.operator = operator;
assertComparable( leftHandExpression, rightHandExpression, nodeBuilder.getSessionFactory() ); assertComparable( leftHandExpression, rightHandExpression, nodeBuilder );
final SqmExpressible<?> expressibleType = QueryHelper.highestPrecedenceType( final SqmExpressible<?> expressibleType = QueryHelper.highestPrecedenceType(
leftHandExpression.getExpressible(), leftHandExpression.getExpressible(),
@ -59,7 +59,7 @@ public class SqmComparisonPredicate extends AbstractNegatableSqmPredicate {
this.leftHandExpression = affirmativeForm.leftHandExpression; this.leftHandExpression = affirmativeForm.leftHandExpression;
this.rightHandExpression = affirmativeForm.rightHandExpression; this.rightHandExpression = affirmativeForm.rightHandExpression;
this.operator = affirmativeForm.operator; this.operator = affirmativeForm.operator;
assertComparable( leftHandExpression, rightHandExpression, nodeBuilder().getSessionFactory() ); assertComparable( leftHandExpression, rightHandExpression, nodeBuilder() );
} }
@Override @Override

View File

@ -136,7 +136,7 @@ public class SqmInListPredicate<T> extends AbstractNegatableSqmPredicate impleme
} }
private void implyListElementType(SqmExpression<?> expression) { private void implyListElementType(SqmExpression<?> expression) {
assertComparable( getTestExpression(), expression, nodeBuilder().getSessionFactory() ); assertComparable( getTestExpression(), expression, nodeBuilder() );
expression.applyInferableType( expression.applyInferableType(
QueryHelper.highestPrecedenceType2( getTestExpression().getExpressible(), expression.getExpressible() ) QueryHelper.highestPrecedenceType2( getTestExpression().getExpressible(), expression.getExpressible() )
); );

View File

@ -42,7 +42,7 @@ public class SqmInSubQueryPredicate<T> extends AbstractNegatableSqmPredicate imp
this.testExpression = testExpression; this.testExpression = testExpression;
this.subQueryExpression = subQueryExpression; this.subQueryExpression = subQueryExpression;
assertComparable( testExpression, subQueryExpression, nodeBuilder.getSessionFactory() ); assertComparable( testExpression, subQueryExpression, nodeBuilder );
final SqmExpressible<?> expressibleType = QueryHelper.highestPrecedenceType2( final SqmExpressible<?> expressibleType = QueryHelper.highestPrecedenceType2(
testExpression.getExpressible(), testExpression.getExpressible(),

View File

@ -39,7 +39,7 @@ public class SqmMemberOfPredicate extends AbstractNegatableSqmPredicate {
final SimpleDomainType<?> simpleDomainType = pluralPath.getReferencedPathSource().getElementType(); final SimpleDomainType<?> simpleDomainType = pluralPath.getReferencedPathSource().getElementType();
if ( !areTypesComparable(leftHandExpression.getNodeType(), simpleDomainType, nodeBuilder.getSessionFactory()) ) { if ( !areTypesComparable( leftHandExpression.getNodeType(), simpleDomainType, nodeBuilder ) ) {
throw new SemanticException( throw new SemanticException(
String.format( String.format(
"Cannot compare left expression of type '%s' with right expression of type '%s'", "Cannot compare left expression of type '%s' with right expression of type '%s'",

View File

@ -12,7 +12,6 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.persister.entity.EntityPersister; 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 org.hibernate.query.sqm.tree.select.SqmSubQuery;
import jakarta.persistence.criteria.Expression; import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.ParameterExpression;
import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Subquery;
import jakarta.persistence.metamodel.EntityType; import jakarta.persistence.metamodel.EntityType;
import jakarta.persistence.metamodel.SingularAttribute; import jakarta.persistence.metamodel.SingularAttribute;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@ -135,12 +132,11 @@ public class SqmUpdateStatement<T>
} }
private void verifyImmutableEntityUpdate(String hql) { private void verifyImmutableEntityUpdate(String hql) {
final SessionFactoryImplementor factory = nodeBuilder().getSessionFactory();
final EntityPersister persister = final EntityPersister persister =
factory.getMappingMetamodel().getEntityDescriptor( getTarget().getEntityName() ); nodeBuilder().getMappingMetamodel().getEntityDescriptor( getTarget().getEntityName() );
if ( !persister.isMutable() ) { if ( !persister.isMutable() ) {
final ImmutableEntityUpdateQueryHandlingMode mode = final ImmutableEntityUpdateQueryHandlingMode mode =
factory.getSessionFactoryOptions().getImmutableEntityUpdateQueryHandlingMode(); nodeBuilder().getImmutableEntityUpdateQueryHandlingMode();
final String querySpaces = Arrays.toString( persister.getQuerySpaces() ); final String querySpaces = Arrays.toString( persister.getQuerySpaces() );
switch ( mode ) { switch ( mode ) {
case WARNING: case WARNING:
@ -155,13 +151,12 @@ public class SqmUpdateStatement<T>
} }
private void verifyUpdateTypesMatch() { private void verifyUpdateTypesMatch() {
final SessionFactoryImplementor factory = nodeBuilder().getSessionFactory();
final List<SqmAssignment<?>> assignments = getSetClause().getAssignments(); final List<SqmAssignment<?>> assignments = getSetClause().getAssignments();
for ( int i = 0; i < assignments.size(); i++ ) { for ( int i = 0; i < assignments.size(); i++ ) {
final SqmAssignment<?> assignment = assignments.get( i ); final SqmAssignment<?> assignment = assignments.get( i );
final SqmPath<?> targetPath = assignment.getTargetPath(); final SqmPath<?> targetPath = assignment.getTargetPath();
final SqmExpression<?> expression = assignment.getValue(); final SqmExpression<?> expression = assignment.getValue();
assertAssignable( null, targetPath, expression, factory ); assertAssignable( null, targetPath, expression, nodeBuilder() );
} }
} }
@ -207,7 +202,7 @@ public class SqmUpdateStatement<T>
else { else {
expression = (SqmExpression) nodeBuilder().value( value ); expression = (SqmExpression) nodeBuilder().value( value );
} }
assertAssignable( null, sqmPath, expression, nodeBuilder().getSessionFactory() ); assertAssignable( null, sqmPath, expression, nodeBuilder() );
applyAssignment( sqmPath, expression ); applyAssignment( sqmPath, expression );
return this; return this;
} }

View File

@ -8,6 +8,7 @@ package org.hibernate.sql.ast.spi;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.query.BindingContext;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
/** /**
@ -16,7 +17,7 @@ import org.hibernate.service.ServiceRegistry;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface SqlAstCreationContext { public interface SqlAstCreationContext extends BindingContext {
/** /**
* The SessionFactory * The SessionFactory
*/ */

View File

@ -8,7 +8,7 @@ package org.hibernate.type;
import java.io.Serializable; 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.type.descriptor.converter.spi.BasicValueConverter;
import org.hibernate.query.BindableType; import org.hibernate.query.BindableType;
import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmExpressible;
@ -83,7 +83,7 @@ public final class BasicTypeReference<T> implements BindableType<T>, Serializabl
} }
@Override @Override
public SqmExpressible<T> resolveExpressible(SessionFactoryImplementor sessionFactory) { public SqmExpressible<T> resolveExpressible(BindingContext bindingContext) {
return sessionFactory.getTypeConfiguration().getBasicTypeRegistry().resolve( this ); return bindingContext.getTypeConfiguration().getBasicTypeRegistry().resolve( this );
} }
} }

View File

@ -37,6 +37,7 @@ import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.metamodel.spi.EmbeddableInstantiator; import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy; import org.hibernate.metamodel.spi.EmbeddableRepresentationStrategy;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.query.BindingContext;
import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.type.descriptor.ValueExtractor; import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType;
@ -844,8 +845,8 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
} }
@Override @Override
public SqmExpressible<?> resolveExpressible(SessionFactoryImplementor sessionFactory) { public SqmExpressible<?> resolveExpressible(BindingContext bindingContext) {
return sessionFactory.getJpaMetamodel().embeddable( getReturnedClass() ); return bindingContext.getJpaMetamodel().embeddable( getReturnedClass() );
} }
@Override @Override

View File

@ -12,6 +12,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.loader.ast.spi.AfterLoadAction; import org.hibernate.loader.ast.spi.AfterLoadAction;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.model.domain.JpaMetamodel;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement; import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
import org.hibernate.service.ServiceRegistry; 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.sql.exec.spi.Callback;
import org.hibernate.testing.orm.junit.BaseSessionFactoryFunctionalTest; import org.hibernate.testing.orm.junit.BaseSessionFactoryFunctionalTest;
import org.hibernate.type.spi.TypeConfiguration;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -80,6 +82,16 @@ public abstract class BaseSqmUnitTest
return sessionFactory().getRuntimeMetamodels().getMappingMetamodel(); return sessionFactory().getRuntimeMetamodels().getMappingMetamodel();
} }
@Override
public TypeConfiguration getTypeConfiguration() {
return sessionFactory().getTypeConfiguration();
}
@Override
public JpaMetamodel getJpaMetamodel() {
return sessionFactory().getJpaMetamodel();
}
@Override @Override
public ServiceRegistry getServiceRegistry() { public ServiceRegistry getServiceRegistry() {
return sessionFactory().getServiceRegistry(); return sessionFactory().getServiceRegistry();

View File

@ -6,8 +6,8 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.query.BindingContext;
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter; import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
import org.hibernate.query.BindableType; import org.hibernate.query.BindableType;
import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmExpressible;
@ -35,7 +35,7 @@ public class ArrayType implements UserType<Array>, BindableType<Array>, BasicVal
} }
@Override @Override
public SqmExpressible<Array> resolveExpressible(SessionFactoryImplementor sessionFactory) { public SqmExpressible<Array> resolveExpressible(BindingContext bindingContext) {
// really a UserType should not implement BindableType // really a UserType should not implement BindableType
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -82,7 +82,6 @@ import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.query.criteria.ValueHandlingMode;
import org.hibernate.query.hql.HqlTranslator; import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.hql.internal.StandardHqlTranslator; import org.hibernate.query.hql.internal.StandardHqlTranslator;
import org.hibernate.query.hql.spi.SqmCreationOptions; import org.hibernate.query.hql.spi.SqmCreationOptions;
@ -152,6 +151,8 @@ public abstract class MockSessionFactory
private final MetadataImplementor bootModel; private final MetadataImplementor bootModel;
private final MetadataContext metadataContext; private final MetadataContext metadataContext;
private final NodeBuilder nodeBuilder;
public MockSessionFactory() { public MockSessionFactory() {
serviceRegistry = StandardServiceRegistryImpl.create( serviceRegistry = StandardServiceRegistryImpl.create(
@ -222,6 +223,8 @@ public abstract class MockSessionFactory
functionFactory.hypotheticalOrderedSetAggregates(); functionFactory.hypotheticalOrderedSetAggregates();
functionFactory.windowFunctions(); functionFactory.windowFunctions();
typeConfiguration.scope((SessionFactoryImplementor) this); typeConfiguration.scope((SessionFactoryImplementor) this);
nodeBuilder = new SqmCriteriaNodeBuilder("", "", this, this, this);
} }
@Override @Override
@ -460,7 +463,7 @@ public abstract class MockSessionFactory
@Override @Override
public QueryInterpretationCache getInterpretationCache() { public QueryInterpretationCache getInterpretationCache() {
return new QueryInterpretationCacheDisabledImpl(this::getStatistics); return new QueryInterpretationCacheDisabledImpl( serviceRegistry );
} }
@Override @Override
@ -475,14 +478,7 @@ public abstract class MockSessionFactory
@Override @Override
public NodeBuilder getCriteriaBuilder() { public NodeBuilder getCriteriaBuilder() {
return new SqmCriteriaNodeBuilder( return nodeBuilder;
"",
"",
this,
false,
ValueHandlingMode.INLINE,
() -> MockSessionFactory.this
);
} }
@Override @Override