From 239f9ff55bab85809ab8114972a0de89c9c3da51 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 5 Sep 2025 10:36:00 +0800 Subject: [PATCH 1/4] clean up some config logic deprecate a method which reports errors using debug logging! --- .../boot/internal/MetadataBuilderImpl.java | 74 ++++++++++--------- .../internal/ConfigurationServiceImpl.java | 6 +- .../config/spi/ConfigurationService.java | 8 +- .../sqm/tree/select/SqmSelectClause.java | 13 ++-- .../oracle/OracleDialectContributor.java | 9 +-- 5 files changed, 58 insertions(+), 52 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java index e41ea25d2783..b7de12ad8b59 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataBuilderImpl.java @@ -10,6 +10,10 @@ import org.hibernate.AnnotationException; import org.hibernate.HibernateException; +import org.hibernate.cfg.CacheSettings; +import org.hibernate.cfg.JpaComplianceSettings; +import org.hibernate.cfg.ManagedBeanSettings; +import org.hibernate.cfg.SchemaToolingSettings; import org.hibernate.context.spi.MultiTenancy; import org.hibernate.type.TimeZoneStorageStrategy; import org.hibernate.annotations.CacheConcurrencyStrategy; @@ -61,7 +65,6 @@ import org.hibernate.boot.spi.MetadataSourcesContributor; import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cache.spi.access.AccessType; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.MappingSettings; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.TimeZoneSupport; @@ -87,10 +90,8 @@ import jakarta.persistence.ConstraintMode; import jakarta.persistence.SharedCacheMode; -import static org.hibernate.cfg.AvailableSettings.JPA_COMPLIANCE; -import static org.hibernate.cfg.AvailableSettings.WRAPPER_ARRAY_HANDLING; -import static org.hibernate.cfg.MappingSettings.XML_FORMAT_MAPPER_LEGACY_FORMAT; import static org.hibernate.engine.config.spi.StandardConverters.BOOLEAN; +import static org.hibernate.engine.config.spi.StandardConverters.STRING; import static org.hibernate.internal.util.NullnessHelper.coalesceSuppliedValues; import static org.hibernate.internal.util.StringHelper.nullIfEmpty; import static org.hibernate.internal.util.collections.CollectionHelper.isNotEmpty; @@ -447,7 +448,7 @@ public MetadataImplementor build() { sources.getHbmXmlBindings(), bootModel, UnsupportedFeatureHandling.fromSetting( - configurationService.getSettings().get( AvailableSettings.TRANSFORM_HBM_XML_FEATURE_HANDLING ), + configurationService.getSettings().get( MappingSettings.TRANSFORM_HBM_XML_FEATURE_HANDLING ), UnsupportedFeatureHandling.ERROR ) ); @@ -505,18 +506,18 @@ public MappingDefaultsImpl(StandardServiceRegistry serviceRegistry) { implicitCatalogName = null; implicitlyQuoteIdentifiers = configService.getSetting( - AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, + MappingSettings.GLOBALLY_QUOTED_IDENTIFIERS, BOOLEAN, false ); implicitCacheAccessType = configService.getSetting( - AvailableSettings.DEFAULT_CACHE_CONCURRENCY_STRATEGY, + CacheSettings.DEFAULT_CACHE_CONCURRENCY_STRATEGY, value -> AccessType.fromExternalName( value.toString() ) ); implicitListClassification = configService.getSetting( - AvailableSettings.DEFAULT_LIST_SEMANTICS, + MappingSettings.DEFAULT_LIST_SEMANTICS, value -> { final CollectionClassification classification = CollectionClassification.interpretSetting( value ); if ( classification != CollectionClassification.LIST && classification != CollectionClassification.BAG ) { @@ -524,7 +525,7 @@ public MappingDefaultsImpl(StandardServiceRegistry serviceRegistry) { String.format( Locale.ROOT, "'%s' should specify either '%s' or '%s' (was '%s')", - AvailableSettings.DEFAULT_LIST_SEMANTICS, + MappingSettings.DEFAULT_LIST_SEMANTICS, java.util.List.class.getName(), java.util.Collection.class.getName(), classification.name() @@ -654,45 +655,49 @@ public MetadataBuildingOptionsImpl(StandardServiceRegistry serviceRegistry) { multiTenancyEnabled = MultiTenancy.isMultiTenancyEnabled( serviceRegistry ); xmlMappingEnabled = configService.getSetting( - AvailableSettings.XML_MAPPING_ENABLED, + MappingSettings.XML_MAPPING_ENABLED, BOOLEAN, true ); - xmlFormatMapperLegacyFormat = configService.getSetting( XML_FORMAT_MAPPER_LEGACY_FORMAT, BOOLEAN, false ); + xmlFormatMapperLegacyFormat = configService.getSetting( + MappingSettings.XML_FORMAT_MAPPER_LEGACY_FORMAT, + BOOLEAN, + false + ); implicitDiscriminatorsForJoinedInheritanceSupported = configService.getSetting( - AvailableSettings.IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS, + MappingSettings.IMPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS, BOOLEAN, false ); explicitDiscriminatorsForJoinedInheritanceSupported = !configService.getSetting( - AvailableSettings.IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS, + MappingSettings.IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS, BOOLEAN, false ); implicitlyForceDiscriminatorInSelect = configService.getSetting( - AvailableSettings.FORCE_DISCRIMINATOR_IN_SELECTS_BY_DEFAULT, + MappingSettings.FORCE_DISCRIMINATOR_IN_SELECTS_BY_DEFAULT, BOOLEAN, false ); sharedCacheMode = configService.getSetting( - AvailableSettings.JAKARTA_SHARED_CACHE_MODE, + CacheSettings.JAKARTA_SHARED_CACHE_MODE, value -> value instanceof SharedCacheMode cacheMode ? cacheMode : SharedCacheMode.valueOf( value.toString() ), configService.getSetting( - AvailableSettings.JPA_SHARED_CACHE_MODE, + CacheSettings.JPA_SHARED_CACHE_MODE, value -> { if ( value == null ) { return null; } DeprecationLogger.DEPRECATION_LOGGER.deprecatedSetting( - AvailableSettings.JPA_SHARED_CACHE_MODE, - AvailableSettings.JAKARTA_SHARED_CACHE_MODE + CacheSettings.JPA_SHARED_CACHE_MODE, + CacheSettings.JAKARTA_SHARED_CACHE_MODE ); return value instanceof SharedCacheMode cacheMode @@ -705,7 +710,7 @@ public MetadataBuildingOptionsImpl(StandardServiceRegistry serviceRegistry) { final RegionFactory regionFactory = serviceRegistry.getService( RegionFactory.class ); defaultCacheAccessType = configService.getSetting( - AvailableSettings.DEFAULT_CACHE_CONCURRENCY_STRATEGY, + CacheSettings.DEFAULT_CACHE_CONCURRENCY_STRATEGY, value -> { if ( value == null ) { return null; @@ -724,15 +729,18 @@ else if ( value instanceof AccessType accessType ) { regionFactory == null ? null : regionFactory.getDefaultAccessType() ); - noConstraintByDefault = ConstraintMode.NO_CONSTRAINT.name().equalsIgnoreCase( configService.getSetting( - AvailableSettings.HBM2DDL_DEFAULT_CONSTRAINT_MODE, - String.class, + final String defaultConstraintMode = configService.getSetting( + SchemaToolingSettings.HBM2DDL_DEFAULT_CONSTRAINT_MODE, + STRING, null - ) ); + ); + noConstraintByDefault = + ConstraintMode.NO_CONSTRAINT.name() + .equalsIgnoreCase( defaultConstraintMode ); implicitNamingStrategy = strategySelector.resolveDefaultableStrategy( ImplicitNamingStrategy.class, - configService.getSettings().get( AvailableSettings.IMPLICIT_NAMING_STRATEGY ), + configService.getSettings().get( MappingSettings.IMPLICIT_NAMING_STRATEGY ), () -> strategySelector.resolveDefaultableStrategy( ImplicitNamingStrategy.class, "default", @@ -742,13 +750,13 @@ else if ( value instanceof AccessType accessType ) { physicalNamingStrategy = strategySelector.resolveDefaultableStrategy( PhysicalNamingStrategy.class, - configService.getSettings().get( AvailableSettings.PHYSICAL_NAMING_STRATEGY ), + configService.getSettings().get( MappingSettings.PHYSICAL_NAMING_STRATEGY ), PhysicalNamingStrategyStandardImpl.INSTANCE ); columnOrderingStrategy = strategySelector.resolveDefaultableStrategy( ColumnOrderingStrategy.class, - configService.getSettings().get( AvailableSettings.COLUMN_ORDERING_STRATEGY ), + configService.getSettings().get( MappingSettings.COLUMN_ORDERING_STRATEGY ), () -> strategySelector.resolveDefaultableStrategy( ColumnOrderingStrategy.class, "default", @@ -757,19 +765,19 @@ else if ( value instanceof AccessType accessType ) { ); useNationalizedCharacterData = configService.getSetting( - AvailableSettings.USE_NATIONALIZED_CHARACTER_DATA, + MappingSettings.USE_NATIONALIZED_CHARACTER_DATA, BOOLEAN, false ); schemaCharset = configService.getSetting( - AvailableSettings.HBM2DDL_CHARSET_NAME, - String.class, + SchemaToolingSettings.HBM2DDL_CHARSET_NAME, + STRING, null ); allowExtensionsInCdi = configService.getSetting( - AvailableSettings.ALLOW_EXTENSIONS_IN_CDI, + ManagedBeanSettings.ALLOW_EXTENSIONS_IN_CDI, BOOLEAN, false ); @@ -975,7 +983,7 @@ public void setBootstrapContext(BootstrapContext bootstrapContext) { private static TimeZoneStorageType resolveTimeZoneStorageStrategy( ConfigurationService configService) { return configService.getSetting( - AvailableSettings.TIMEZONE_DEFAULT_STORAGE, + MappingSettings.TIMEZONE_DEFAULT_STORAGE, value -> TimeZoneStorageType.valueOf( value.toString() ), TimeZoneStorageType.DEFAULT ); @@ -985,7 +993,7 @@ private static WrapperArrayHandling resolveWrapperArrayHandling( ConfigurationService configService) { return coalesceSuppliedValues( () -> configService.getSetting( - WRAPPER_ARRAY_HANDLING, + MappingSettings.WRAPPER_ARRAY_HANDLING, WrapperArrayHandling::interpretExternalSettingLeniently ), () -> resolveFallbackWrapperArrayHandling( configService ) @@ -1005,7 +1013,7 @@ private static WrapperArrayHandling pickWrapperArrayHandling(Dialect dialect) { private static WrapperArrayHandling resolveFallbackWrapperArrayHandling( ConfigurationService configService) { - return configService.getSetting( JPA_COMPLIANCE, BOOLEAN, false ) + return configService.getSetting( JpaComplianceSettings.JPA_COMPLIANCE, BOOLEAN, false ) ? WrapperArrayHandling.PICK // JPA compliance was enabled. Use PICK : WrapperArrayHandling.DISALLOW; } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/config/internal/ConfigurationServiceImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/config/internal/ConfigurationServiceImpl.java index 64ebe71be3c1..fcb5783c6f9d 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/config/internal/ConfigurationServiceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/config/internal/ConfigurationServiceImpl.java @@ -62,11 +62,7 @@ public void injectServices(ServiceRegistryImplementor serviceRegistry) { @Override public @PolyNull T getSetting(String name, Converter converter, @PolyNull T defaultValue) { final Object value = settings.get( name ); - if ( value == null ) { - return defaultValue; - } - - return converter.convert( value ); + return value == null ? defaultValue : converter.convert( value ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/engine/config/spi/ConfigurationService.java b/hibernate-core/src/main/java/org/hibernate/engine/config/spi/ConfigurationService.java index a53a80f59fc9..d270f8946443 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/config/spi/ConfigurationService.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/config/spi/ConfigurationService.java @@ -38,7 +38,9 @@ public interface ConfigurationService extends Service { * @param converter The converter to apply * @param The Java type of the conversion * - * @return The converted (typed) setting. May return {@code null} (see {@link #getSetting(String, Class, Object)}) + * @return The converted (typed) setting. + * May return {@code null} + * (see {@link #getSetting(String, Class, Object)}) */ @Nullable T getSetting(String name, Converter converter); @@ -64,7 +66,11 @@ public interface ConfigurationService extends Service { * @param The Java type of the conversion * * @return The converted (typed) setting. Will be the defaultValue if no such setting was defined. + * + * @deprecated Use {@link #getSetting(String, Converter, Object)}. + * This method does not report errors correctly. */ + @Deprecated(since = "7.2") @PolyNull T getSetting(String name, Class expected, @PolyNull T defaultValue); /** diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSelectClause.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSelectClause.java index cf905603cdfc..b622be205d3a 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSelectClause.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSelectClause.java @@ -5,7 +5,6 @@ package org.hibernate.query.sqm.tree.select; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Objects; @@ -16,6 +15,8 @@ import org.hibernate.query.sqm.tree.expression.SqmExpression; import org.hibernate.type.descriptor.java.JavaType; +import static java.util.Collections.emptyList; +import static java.util.Collections.unmodifiableList; import static org.hibernate.internal.util.collections.CollectionHelper.arrayList; /** @@ -23,7 +24,8 @@ * * @author Steve Ebersole */ -public class SqmSelectClause extends AbstractSqmNode implements SqmAliasedExpressionContainer>, JpaSelection { +public class SqmSelectClause extends AbstractSqmNode + implements SqmAliasedExpressionContainer>, JpaSelection { private boolean distinct; private List> selections; @@ -64,12 +66,7 @@ public void makeDistinct(boolean distinct) { } public List> getSelections() { - if ( selections == null ) { - return Collections.emptyList(); - } - else { - return Collections.unmodifiableList( selections ); - } + return selections == null ? emptyList() : unmodifiableList( selections ); } public void addSelection(SqmSelection selection) { diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleDialectContributor.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleDialectContributor.java index 849b56506fd8..a80ab64efc68 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleDialectContributor.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/oracle/OracleDialectContributor.java @@ -26,7 +26,7 @@ public class OracleDialectContributor implements ContributorImplementor { public OracleDialectContributor(ServiceRegistry serviceRegistry) { this.serviceRegistry = serviceRegistry; - final var cfgService = getServiceRegistry().getService( ConfigurationService.class ); + final var cfgService = getServiceRegistry().requireService( ConfigurationService.class ); this.useSTGeometry = cfgService.getSetting( HibernateSpatialConfigurationSettings.ORACLE_OGC_STRICT, StandardConverters.BOOLEAN, @@ -37,15 +37,14 @@ public OracleDialectContributor(ServiceRegistry serviceRegistry) { @Override public void contributeJdbcTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { HSMessageLogger.SPATIAL_MSG_LOGGER.typeContributions( this.getClass().getCanonicalName() ); - final ConfigurationService cfgService = getServiceRegistry().getService( ConfigurationService.class ); - final StrategySelector strategySelector = getServiceRegistry().getService( StrategySelector.class ); - + final var cfgService = getServiceRegistry().requireService( ConfigurationService.class ); + final var strategySelector = getServiceRegistry().requireService( StrategySelector.class ); final ConnectionFinder connectionFinder = strategySelector.resolveStrategy( ConnectionFinder.class, cfgService.getSetting( HibernateSpatialConfigurationSettings.CONNECTION_FINDER, - String.class, + StandardConverters.STRING, "org.geolatte.geom.codec.db.oracle.DefaultConnectionFinder" ) ); From af847f918e091b1e4e5fc97a8b495fb9fb86bb67 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 5 Sep 2025 10:49:02 +0800 Subject: [PATCH 2/4] optimize some imports --- .../internal/SchemaManagerImpl.java | 37 +++++++++++-------- .../result/internal/OutputsImpl.java | 6 +-- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/relational/internal/SchemaManagerImpl.java b/hibernate-core/src/main/java/org/hibernate/relational/internal/SchemaManagerImpl.java index 20f39ae51056..f74254d20900 100644 --- a/hibernate-core/src/main/java/org/hibernate/relational/internal/SchemaManagerImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/relational/internal/SchemaManagerImpl.java @@ -5,7 +5,6 @@ package org.hibernate.relational.internal; import org.hibernate.boot.spi.MetadataImplementor; -import org.hibernate.cfg.AvailableSettings; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.relational.SchemaManager; import org.hibernate.tool.schema.Action; @@ -17,6 +16,12 @@ import jakarta.persistence.SchemaValidationException; +import static org.hibernate.cfg.MappingSettings.DEFAULT_CATALOG; +import static org.hibernate.cfg.MappingSettings.DEFAULT_SCHEMA; +import static org.hibernate.cfg.SchemaToolingSettings.JAKARTA_HBM2DDL_CREATE_SCHEMAS; +import static org.hibernate.cfg.SchemaToolingSettings.JAKARTA_HBM2DDL_DATABASE_ACTION; +import static org.hibernate.cfg.SchemaToolingSettings.JAKARTA_HBM2DDL_SCRIPTS_ACTION; + /** * Implementation of {@link SchemaManager}, backed by a {@link SessionFactoryImplementor} * and {@link SchemaManagementToolCoordinator}. @@ -57,19 +62,19 @@ public SchemaManager forCatalog(String catalogName) { private void addSchemaAndCatalog(Map properties) { if ( schemaName != null ) { - properties.put( AvailableSettings.DEFAULT_SCHEMA, schemaName ); + properties.put( DEFAULT_SCHEMA, schemaName ); } if ( catalogName != null ) { - properties.put( AvailableSettings.DEFAULT_CATALOG, catalogName ); + properties.put( DEFAULT_CATALOG, catalogName ); } } @Override public void exportMappedObjects(boolean createSchemas) { Map properties = new HashMap<>( sessionFactory.getProperties() ); - properties.put( AvailableSettings.JAKARTA_HBM2DDL_DATABASE_ACTION, Action.CREATE_ONLY ); - properties.put( AvailableSettings.JAKARTA_HBM2DDL_SCRIPTS_ACTION, Action.NONE ); - properties.put( AvailableSettings.JAKARTA_HBM2DDL_CREATE_SCHEMAS, createSchemas ); + properties.put( JAKARTA_HBM2DDL_DATABASE_ACTION, Action.CREATE_ONLY ); + properties.put( JAKARTA_HBM2DDL_SCRIPTS_ACTION, Action.NONE ); + properties.put( JAKARTA_HBM2DDL_CREATE_SCHEMAS, createSchemas ); addSchemaAndCatalog( properties ); SchemaManagementToolCoordinator.process( metadata, @@ -82,9 +87,9 @@ public void exportMappedObjects(boolean createSchemas) { @Override public void dropMappedObjects(boolean dropSchemas) { Map properties = new HashMap<>( sessionFactory.getProperties() ); - properties.put( AvailableSettings.JAKARTA_HBM2DDL_DATABASE_ACTION, Action.DROP ); - properties.put( AvailableSettings.JAKARTA_HBM2DDL_SCRIPTS_ACTION, Action.NONE ); - properties.put( AvailableSettings.JAKARTA_HBM2DDL_CREATE_SCHEMAS, dropSchemas ); + properties.put( JAKARTA_HBM2DDL_DATABASE_ACTION, Action.DROP ); + properties.put( JAKARTA_HBM2DDL_SCRIPTS_ACTION, Action.NONE ); + properties.put( JAKARTA_HBM2DDL_CREATE_SCHEMAS, dropSchemas ); addSchemaAndCatalog( properties ); SchemaManagementToolCoordinator.process( metadata, @@ -97,9 +102,9 @@ public void dropMappedObjects(boolean dropSchemas) { @Override public void validateMappedObjects() { Map properties = new HashMap<>( sessionFactory.getProperties() ); - properties.put( AvailableSettings.JAKARTA_HBM2DDL_DATABASE_ACTION, Action.VALIDATE ); - properties.put( AvailableSettings.JAKARTA_HBM2DDL_SCRIPTS_ACTION, Action.NONE ); - properties.put( AvailableSettings.JAKARTA_HBM2DDL_CREATE_SCHEMAS, false ); + properties.put( JAKARTA_HBM2DDL_DATABASE_ACTION, Action.VALIDATE ); + properties.put( JAKARTA_HBM2DDL_SCRIPTS_ACTION, Action.NONE ); + properties.put( JAKARTA_HBM2DDL_CREATE_SCHEMAS, false ); addSchemaAndCatalog( properties ); SchemaManagementToolCoordinator.process( metadata, @@ -112,8 +117,8 @@ public void validateMappedObjects() { @Override public void truncateMappedObjects() { Map properties = new HashMap<>( sessionFactory.getProperties() ); - properties.put( AvailableSettings.JAKARTA_HBM2DDL_DATABASE_ACTION, Action.TRUNCATE ); - properties.put( AvailableSettings.JAKARTA_HBM2DDL_SCRIPTS_ACTION, Action.NONE ); + properties.put( JAKARTA_HBM2DDL_DATABASE_ACTION, Action.TRUNCATE ); + properties.put( JAKARTA_HBM2DDL_SCRIPTS_ACTION, Action.NONE ); addSchemaAndCatalog( properties ); SchemaManagementToolCoordinator.process( metadata, @@ -126,8 +131,8 @@ public void truncateMappedObjects() { @Override public void populate() { Map properties = new HashMap<>( sessionFactory.getProperties() ); - properties.put( AvailableSettings.JAKARTA_HBM2DDL_DATABASE_ACTION, Action.POPULATE ); - properties.put( AvailableSettings.JAKARTA_HBM2DDL_SCRIPTS_ACTION, Action.NONE ); + properties.put( JAKARTA_HBM2DDL_DATABASE_ACTION, Action.POPULATE ); + properties.put( JAKARTA_HBM2DDL_SCRIPTS_ACTION, Action.NONE ); addSchemaAndCatalog( properties ); SchemaManagementToolCoordinator.process( metadata, diff --git a/hibernate-core/src/main/java/org/hibernate/result/internal/OutputsImpl.java b/hibernate-core/src/main/java/org/hibernate/result/internal/OutputsImpl.java index 62812199e290..616017b2fc5c 100644 --- a/hibernate-core/src/main/java/org/hibernate/result/internal/OutputsImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/result/internal/OutputsImpl.java @@ -14,8 +14,6 @@ import org.hibernate.JDBCException; import org.hibernate.engine.jdbc.spi.SqlStatementLogger; -import org.hibernate.event.monitor.spi.EventMonitor; -import org.hibernate.event.monitor.spi.DiagnosticEvent; import org.hibernate.internal.CoreLogging; import org.hibernate.procedure.internal.ProcedureCallImpl; import org.hibernate.result.Output; @@ -67,8 +65,8 @@ protected void executeStatement() { executeStartNanos = System.nanoTime(); } final var session = context.getSession(); - final EventMonitor eventMonitor = session.getEventMonitor(); - final DiagnosticEvent jdbcPreparedStatementExecutionEvent = + final var eventMonitor = session.getEventMonitor(); + final var jdbcPreparedStatementExecutionEvent = eventMonitor.beginJdbcPreparedStatementExecutionEvent(); try { final boolean isResultSet = jdbcStatement.execute(); From 7cc724538eef5926f6844c211c2583b0700a62e8 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 5 Sep 2025 09:42:44 +0200 Subject: [PATCH 3/4] lots of cleanups in the Query hierarchy --- .../procedure/internal/ProcedureCallImpl.java | 298 ++++++++++-------- .../spi/AbstractCommonQueryContract.java | 187 +++++------ .../hibernate/query/spi/AbstractQuery.java | 35 +- .../query/spi/AbstractSelectionQuery.java | 49 +-- .../query/sql/internal/NativeQueryImpl.java | 169 +++++----- .../internal/AbstractSqmSelectionQuery.java | 67 ++-- .../query/sqm/internal/SqmQueryImpl.java | 239 +++++++------- .../sqm/internal/SqmSelectionQueryImpl.java | 117 ++++--- 8 files changed, 581 insertions(+), 580 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java b/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java index 46f7a61ffe40..798d3f729b57 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java @@ -4,11 +4,9 @@ */ package org.hibernate.procedure.internal; -import java.sql.CallableStatement; import java.sql.SQLException; import java.sql.Types; import java.util.ArrayList; -import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.HashSet; @@ -21,20 +19,16 @@ import org.hibernate.HibernateException; import org.hibernate.LockOptions; import org.hibernate.ScrollMode; -import org.hibernate.engine.jdbc.spi.JdbcCoordinator; -import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.RootGraph; import org.hibernate.graph.spi.RootGraphImplementor; -import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.procedure.NoSuchParameterException; import org.hibernate.procedure.ParameterStrategyException; import org.hibernate.procedure.ProcedureCall; import org.hibernate.procedure.ProcedureOutputs; -import org.hibernate.procedure.spi.CallableStatementSupport; import org.hibernate.procedure.spi.FunctionReturnImplementor; import org.hibernate.procedure.spi.NamedCallableQueryMemento; import org.hibernate.procedure.spi.ParameterStrategy; @@ -42,9 +36,9 @@ import org.hibernate.procedure.spi.ProcedureParameterImplementor; import org.hibernate.query.KeyedPage; import org.hibernate.query.KeyedResultList; -import org.hibernate.type.BindableType; import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.SqmBindableType; +import org.hibernate.sql.exec.spi.JdbcOperationQueryCall; import org.hibernate.type.OutputableType; import org.hibernate.query.Query; import org.hibernate.query.QueryParameter; @@ -54,7 +48,6 @@ import org.hibernate.query.spi.AbstractQuery; import org.hibernate.query.spi.MutableQueryOptions; import org.hibernate.query.spi.QueryImplementor; -import org.hibernate.query.spi.QueryParameterBinding; import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.query.spi.ScrollableResultsImplementor; import org.hibernate.query.sqm.SqmExpressible; @@ -64,14 +57,10 @@ import org.hibernate.result.internal.OutputsExecutionContext; import org.hibernate.result.spi.ResultContext; import org.hibernate.sql.ast.tree.expression.JdbcParameter; -import org.hibernate.sql.exec.internal.JdbcCallRefCursorExtractorImpl; import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl; import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl; -import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.JdbcCallParameterRegistration; import org.hibernate.sql.exec.spi.JdbcCallRefCursorExtractor; -import org.hibernate.sql.exec.spi.JdbcOperationQueryCall; -import org.hibernate.sql.exec.spi.JdbcParameterBinder; import org.hibernate.sql.exec.spi.JdbcParameterBindings; import org.hibernate.sql.results.NoMoreOutputsException; import org.hibernate.type.BasicType; @@ -89,14 +78,18 @@ import jakarta.persistence.metamodel.Type; import static java.lang.Boolean.parseBoolean; +import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static java.util.Collections.emptySet; import static java.util.Collections.unmodifiableList; import static java.util.Collections.unmodifiableSet; import static org.hibernate.internal.util.StringHelper.join; +import static org.hibernate.internal.util.collections.CollectionHelper.makeCopy; import static org.hibernate.jpa.HibernateHints.HINT_CALLABLE_FUNCTION; import static org.hibernate.jpa.HibernateHints.HINT_CALLABLE_FUNCTION_RETURN_TYPE; import static org.hibernate.procedure.internal.NamedCallableQueryMementoImpl.ParameterMementoImpl.fromRegistration; +import static org.hibernate.procedure.internal.Util.resolveResultSetMappingClasses; +import static org.hibernate.procedure.internal.Util.resolveResultSetMappings; import static org.hibernate.query.results.ResultSetMapping.resolveResultSetMapping; /** @@ -123,6 +116,13 @@ public class ProcedureCallImpl private ProcedureOutputsImpl outputs; + private static String mappingId(String procedureName, Class[] resultClasses) { + return procedureName + ":" + join( ",", resultClasses ); + } + + private static String mappingId(String procedureName, String[] resultSetMappingNames) { + return procedureName + ":" + join( ",", resultSetMappingNames ); + } /** * The no-returns form. @@ -134,12 +134,12 @@ public ProcedureCallImpl(SharedSessionContractImplementor session, String proced super( session ); this.procedureName = procedureName; - this.parameterMetadata = new ProcedureParameterMetadataImpl(); - this.parameterBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() ); + parameterMetadata = new ProcedureParameterMetadataImpl(); + parameterBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() ); - this.resultSetMapping = resolveResultSetMapping( procedureName, true, session.getSessionFactory() ); + resultSetMapping = resolveResultSetMapping( procedureName, true, session.getSessionFactory() ); - this.synchronizedQuerySpaces = null; + synchronizedQuerySpaces = null; } /** @@ -156,16 +156,16 @@ public ProcedureCallImpl(SharedSessionContractImplementor session, String proced this.procedureName = procedureName; - this.parameterMetadata = new ProcedureParameterMetadataImpl(); - this.parameterBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() ); + final var factory = session.getSessionFactory(); - this.synchronizedQuerySpaces = new HashSet<>(); + parameterMetadata = new ProcedureParameterMetadataImpl(); + parameterBindings = new ProcedureParamBindings( parameterMetadata, factory ); - final String mappingId = procedureName + ":" + join( ",", resultClasses ); + synchronizedQuerySpaces = new HashSet<>(); - this.resultSetMapping = resolveResultSetMapping( mappingId, session.getSessionFactory() ); + resultSetMapping = resolveResultSetMapping( mappingId( procedureName, resultClasses ), factory ); - Util.resolveResultSetMappingClasses( + resolveResultSetMappingClasses( resultClasses, resultSetMapping, synchronizedQuerySpaces::add, @@ -190,13 +190,14 @@ public ProcedureCallImpl( this.procedureName = procedureName; - this.parameterMetadata = new ProcedureParameterMetadataImpl(); - this.parameterBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() ); + final var factory = session.getSessionFactory(); - this.synchronizedQuerySpaces = new HashSet<>(); + parameterMetadata = new ProcedureParameterMetadataImpl(); + parameterBindings = new ProcedureParamBindings( parameterMetadata, factory ); - final String mappingId = procedureName + ":" + join( ",", resultSetMappingNames ); - this.resultSetMapping = resolveResultSetMapping( mappingId, session.getSessionFactory() ); + synchronizedQuerySpaces = new HashSet<>(); + + resultSetMapping = resolveResultSetMapping( mappingId( procedureName, resultSetMappingNames ), factory ); Util.resolveResultSetMappingNames( resultSetMappingNames, @@ -215,16 +216,18 @@ public ProcedureCallImpl( ProcedureCallImpl(SharedSessionContractImplementor session, NamedCallableQueryMemento memento) { super( session ); - this.procedureName = memento.getCallableName(); + procedureName = memento.getCallableName(); + + final var factory = session.getSessionFactory(); - this.parameterMetadata = new ProcedureParameterMetadataImpl( memento, session ); - this.parameterBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() ); + parameterMetadata = new ProcedureParameterMetadataImpl( memento, session ); + parameterBindings = new ProcedureParamBindings( parameterMetadata, factory ); - this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() ); + synchronizedQuerySpaces = makeCopy( memento.getQuerySpaces() ); - this.resultSetMapping = resolveResultSetMapping( memento.getRegistrationName(), session.getSessionFactory() ); + resultSetMapping = resolveResultSetMapping( memento.getRegistrationName(), factory ); - Util.resolveResultSetMappings( + resolveResultSetMappings( memento.getResultSetMappingNames(), memento.getResultSetMappingClasses(), resultSetMapping, @@ -247,17 +250,18 @@ public ProcedureCallImpl( Class... resultTypes) { super( session ); - this.procedureName = memento.getCallableName(); + procedureName = memento.getCallableName(); - this.parameterMetadata = new ProcedureParameterMetadataImpl( memento, session ); - this.parameterBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() ); + final var factory = session.getSessionFactory(); - this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() ); + parameterMetadata = new ProcedureParameterMetadataImpl( memento, session ); + parameterBindings = new ProcedureParamBindings( parameterMetadata, factory ); - final String mappingId = procedureName + ":" + join( ",", resultTypes ); - this.resultSetMapping = resolveResultSetMapping( mappingId, session.getSessionFactory() ); + synchronizedQuerySpaces = makeCopy( memento.getQuerySpaces() ); - Util.resolveResultSetMappings( + resultSetMapping = resolveResultSetMapping( mappingId( procedureName, resultTypes ), factory ); + + resolveResultSetMappings( null, resultTypes, resultSetMapping, @@ -274,17 +278,18 @@ public ProcedureCallImpl( String... resultSetMappingNames) { super( session ); - this.procedureName = memento.getCallableName(); + procedureName = memento.getCallableName(); + + final var factory = session.getSessionFactory(); - this.parameterMetadata = new ProcedureParameterMetadataImpl( memento, session ); - this.parameterBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() ); + parameterMetadata = new ProcedureParameterMetadataImpl( memento, session ); + parameterBindings = new ProcedureParamBindings( parameterMetadata, factory ); - this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() ); + synchronizedQuerySpaces = makeCopy( memento.getQuerySpaces() ); - final String mappingId = procedureName + ":" + join( ",", resultSetMappingNames ); - this.resultSetMapping = resolveResultSetMapping( mappingId, session.getSessionFactory() ); + resultSetMapping = resolveResultSetMapping( mappingId( procedureName, resultSetMappingNames ), factory ); - Util.resolveResultSetMappings( + resolveResultSetMappings( resultSetMappingNames, null, resultSetMapping, @@ -301,10 +306,11 @@ private void applyCallableFunctionHint() { (index, resultBuilder) -> resultTypes.add( resultBuilder.getJavaType() ) ); if ( resultTypes.size() == 1 ) { - final BasicType type = - getTypeConfiguration().getBasicTypeForJavaType( resultTypes.get(0) ); - if ( type != null ) { - markAsFunctionCall( type ); + final var basicType = + getTypeConfiguration() + .getBasicTypeForJavaType( resultTypes.get(0) ); + if ( basicType != null ) { + markAsFunctionCall( basicType ); } else { markAsFunctionCallRefRefCursor(); @@ -361,7 +367,7 @@ private void markAsFunctionCallRefRefCursor() { @Override public ProcedureCallImpl markAsFunctionCall(Class resultType) { - final BasicType basicType = getTypeConfiguration().getBasicTypeForJavaType( resultType ); + final var basicType = getTypeConfiguration().getBasicTypeForJavaType( resultType ); if ( basicType == null ) { throw new IllegalArgumentException( "Could not resolve a BasicType for the java type: " + resultType.getName() ); } @@ -480,9 +486,8 @@ public ProcedureCallImplementor registerStoredProcedureParameter( @Override public ProcedureParameter registerParameter(int position, Class javaType, ParameterMode mode) { - final BindableType parameterType = - getSessionFactory().getMappingMetamodel().resolveParameterBindType( javaType ); - final ProcedureParameterImpl procedureParameter = + final var parameterType = getMappingMetamodel().resolveParameterBindType( javaType ); + final var procedureParameter = new ProcedureParameterImpl<>( position, mode, getExpressibleJavaType( parameterType ), parameterType ); registerParameter( procedureParameter ); return procedureParameter; @@ -493,8 +498,8 @@ public ProcedureParameter registerParameter( int position, Type typeReference, ParameterMode mode) { - final SqmBindableType expressible = resolveExpressible( typeReference ); - final ProcedureParameterImpl procedureParameter = + final var expressible = resolveExpressible( typeReference ); + final var procedureParameter = new ProcedureParameterImpl<>( position, mode, typeReference.getJavaType(), expressible ); registerParameter( procedureParameter ); return procedureParameter; @@ -515,9 +520,8 @@ public ProcedureParameterImplementor getParameterRegistration(int position) { @Override public ProcedureParameterImplementor registerParameter(String name, Class javaType, ParameterMode mode) { - final BindableType parameterType = - getSessionFactory().getMappingMetamodel().resolveParameterBindType( javaType ); - final ProcedureParameterImpl parameter = + final var parameterType = getMappingMetamodel().resolveParameterBindType( javaType ); + final var parameter = new ProcedureParameterImpl<>( name, mode, getExpressibleJavaType( parameterType ), parameterType ); registerParameter( parameter ); return parameter; @@ -528,7 +532,7 @@ private Class getExpressibleJavaType(Type parameterType) { return null; } else { - final SqmExpressible sqmExpressible = getNodeBuilder().resolveExpressible( parameterType ); + final var sqmExpressible = getNodeBuilder().resolveExpressible( parameterType ); assert sqmExpressible != null; return sqmExpressible.getExpressibleJavaType().getJavaTypeClass(); } @@ -543,8 +547,8 @@ public ProcedureParameterImplementor registerParameter( String name, Type typeReference, ParameterMode mode) { - final SqmBindableType expressible = resolveExpressible( typeReference ); - final ProcedureParameterImpl parameter = + final var expressible = resolveExpressible( typeReference ); + final var parameter = new ProcedureParameterImpl<>( name, mode, typeReference.getJavaType(), expressible ); registerParameter( parameter ); return parameter; @@ -583,39 +587,22 @@ private ProcedureOutputsImpl buildOutputs() { // both: (1) add the `? = ` part and also (2) register a REFCURSOR parameter for DBs (Oracle, PGSQL) that // need it. - final JdbcServices jdbcServices = getSession().getJdbcServices(); + final var jdbcServices = getSession().getJdbcServices(); + final var callableStatementSupport = + jdbcServices.getJdbcEnvironment().getDialect() + .getCallableStatementSupport(); - final CallableStatementSupport callableStatementSupport = - jdbcServices.getJdbcEnvironment().getDialect().getCallableStatementSupport(); - final JdbcOperationQueryCall call = callableStatementSupport.interpretCall( this ); + final var call = callableStatementSupport.interpretCall( this ); - final Map, JdbcCallParameterRegistration> parameterRegistrations = new IdentityHashMap<>(); - final List refCursorExtractors = new ArrayList<>(); - if ( call.getFunctionReturn() != null ) { - parameterRegistrations.put( functionReturn, call.getFunctionReturn() ); - final JdbcCallRefCursorExtractorImpl refCursorExtractor = call.getFunctionReturn().getRefCursorExtractor(); - if ( refCursorExtractor != null ) { - refCursorExtractors.add( refCursorExtractor ); - } - } - final List> registrations = - getParameterMetadata().getRegistrationsAsList(); - final List jdbcParameters = call.getParameterRegistrations(); - for ( int i = 0; i < registrations.size(); i++ ) { - final JdbcCallParameterRegistration jdbcCallParameterRegistration = jdbcParameters.get( i ); - parameterRegistrations.put( registrations.get( i ), jdbcCallParameterRegistration ); - final JdbcCallRefCursorExtractorImpl refCursorExtractor = - jdbcCallParameterRegistration.getRefCursorExtractor(); - if ( refCursorExtractor != null ) { - refCursorExtractors.add( refCursorExtractor ); - } - } + final var parameterRegistrations = collectParameterRegistrations( call ); + final var refCursorExtractors = collectRefCursorExtractors( call ); - final JdbcCoordinator jdbcCoordinator = getSession().getJdbcCoordinator(); + final var jdbcCoordinator = getSession().getJdbcCoordinator(); final String sqlString = call.getSqlString(); - final CallableStatement statement = - jdbcCoordinator.getStatementPreparer().prepareCallableStatement( sqlString ); + final var statement = + jdbcCoordinator.getStatementPreparer() + .prepareCallableStatement( sqlString ); try { // Register the parameter mode and type callableStatementSupport.registerParameters( @@ -626,39 +613,13 @@ private ProcedureOutputsImpl buildOutputs() { getSession() ); - // Apply the parameter bindings - final JdbcParameterBindings jdbcParameterBindings = - new JdbcParameterBindingsImpl( parameterRegistrations.size() ); - for ( var entry : parameterRegistrations.entrySet() ) { - final JdbcCallParameterRegistration registration = entry.getValue(); - if ( registration.getParameterBinder() != null ) { - final ProcedureParameter parameter = entry.getKey(); - final QueryParameterBinding binding = getParameterBindings().getBinding( parameter ); - if ( !binding.isBound() ) { - if ( parameter.getPosition() == null ) { - throw new IllegalArgumentException( "The parameter named [" + parameter + "] was not set! You need to call the setParameter method." ); - } - else { - throw new IllegalArgumentException( "The parameter at position [" + parameter + "] was not set! You need to call the setParameter method." ); - } - } - final JdbcMapping parameterType = (JdbcMapping) registration.getParameterType(); - jdbcParameterBindings.addBinding( - (JdbcParameter) registration.getParameterBinder(), - new JdbcParameterBindingImpl( - parameterType, - parameterType.convertToRelationalValue( binding.getBindValue() ) - ) - ); - } - } - - final ExecutionContext executionContext = new OutputsExecutionContext( getSession() ); + final var jdbcParameterBindings = parameterBindings( parameterRegistrations ); + final var executionContext = new OutputsExecutionContext( getSession() ); // Note that this should actually happen in an executor int paramBindingPosition = call.getFunctionReturn() == null ? 1 : 2; - for ( JdbcParameterBinder parameterBinder : call.getParameterBinders() ) { + for ( var parameterBinder : call.getParameterBinders() ) { parameterBinder.bindParameterValue( statement, paramBindingPosition, @@ -670,7 +631,7 @@ private ProcedureOutputsImpl buildOutputs() { } catch (SQLException e) { jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( statement ); - getSession().getJdbcCoordinator().afterStatementExecution(); + jdbcCoordinator.afterStatementExecution(); throw jdbcServices.getSqlExceptionHelper().convert( e, "Error registering CallableStatement parameters", @@ -688,6 +649,71 @@ private ProcedureOutputsImpl buildOutputs() { } + private Map, JdbcCallParameterRegistration> collectParameterRegistrations(JdbcOperationQueryCall call) { + final Map, JdbcCallParameterRegistration> parameterRegistrations = new IdentityHashMap<>(); + if ( call.getFunctionReturn() != null ) { + parameterRegistrations.put( functionReturn, call.getFunctionReturn() ); + } + final var registrations = getParameterMetadata().getRegistrationsAsList(); + final var jdbcParameters = call.getParameterRegistrations(); + for ( int i = 0; i < registrations.size(); i++ ) { + final var jdbcCallParameterRegistration = jdbcParameters.get( i ); + parameterRegistrations.put( registrations.get( i ), jdbcCallParameterRegistration ); + } + return parameterRegistrations; + } + + private List collectRefCursorExtractors(JdbcOperationQueryCall call) { + final List refCursorExtractors = new ArrayList<>(); + if ( call.getFunctionReturn() != null ) { + final var refCursorExtractor = call.getFunctionReturn().getRefCursorExtractor(); + if ( refCursorExtractor != null ) { + refCursorExtractors.add( refCursorExtractor ); + } + } + final var registrations = getParameterMetadata().getRegistrationsAsList(); + final var jdbcParameters = call.getParameterRegistrations(); + for ( int i = 0; i < registrations.size(); i++ ) { + final var jdbcCallParameterRegistration = jdbcParameters.get( i ); + final var refCursorExtractor = jdbcCallParameterRegistration.getRefCursorExtractor(); + if ( refCursorExtractor != null ) { + refCursorExtractors.add( refCursorExtractor ); + } + } + return refCursorExtractors; + } + + private JdbcParameterBindings parameterBindings( + Map, JdbcCallParameterRegistration> parameterRegistrations) { + final JdbcParameterBindings jdbcParameterBindings = + new JdbcParameterBindingsImpl( parameterRegistrations.size() ); + for ( var entry : parameterRegistrations.entrySet() ) { + final var registration = entry.getValue(); + final var parameterBinder = registration.getParameterBinder(); + if ( parameterBinder != null ) { + final var parameter = entry.getKey(); + final var binding = getParameterBindings().getBinding( parameter ); + if ( !binding.isBound() ) { + if ( parameter.getPosition() == null ) { + throw new IllegalArgumentException( "The parameter named [" + parameter + "] was not set! You need to call the setParameter method." ); + } + else { + throw new IllegalArgumentException( "The parameter at position [" + parameter + "] was not set! You need to call the setParameter method." ); + } + } + final var parameterType = (JdbcMapping) registration.getParameterType(); + jdbcParameterBindings.addBinding( + (JdbcParameter) parameterBinder, + new JdbcParameterBindingImpl( + parameterType, + parameterType.convertToRelationalValue( binding.getBindValue() ) + ) + ); + } + } + return jdbcParameterBindings; + } + @Override public String getQueryString() { return null; @@ -719,22 +745,18 @@ public ProcedureCallImplementor addSynchronizedQuerySpace(String querySpace) @Override public ProcedureCallImplementor addSynchronizedEntityName(String entityName) { - final EntityPersister entityDescriptor = - this.getSessionFactory().getMappingMetamodel() - .getEntityDescriptor( entityName ); + final var entityDescriptor = getMappingMetamodel().getEntityDescriptor( entityName ); addSynchronizedQuerySpaces( entityDescriptor ); return this; } protected void addSynchronizedQuerySpaces(EntityPersister persister) { - synchronizedQuerySpaces().addAll( Arrays.asList( (String[]) persister.getQuerySpaces() ) ); + synchronizedQuerySpaces().addAll( asList( (String[]) persister.getQuerySpaces() ) ); } @Override public ProcedureCallImplementor addSynchronizedEntityClass(@SuppressWarnings("rawtypes") Class entityClass) { - final EntityPersister entityDescriptor = - this.getSessionFactory().getMappingMetamodel() - .getEntityDescriptor( entityClass ); + final var entityDescriptor = getMappingMetamodel().getEntityDescriptor( entityClass ); addSynchronizedQuerySpaces( entityDescriptor ); return this; } @@ -769,14 +791,14 @@ private static List toParameterMemen // none... return emptyList(); } - - final List mementos = new ArrayList<>(); - - parameterMetadata.visitRegistrations( - queryParameter -> mementos.add( fromRegistration( (ProcedureParameterImplementor) queryParameter) ) - ); - - return mementos; + else { + final List mementos = new ArrayList<>(); + parameterMetadata.visitRegistrations( + queryParameter -> mementos.add( + fromRegistration( (ProcedureParameterImplementor) queryParameter ) ) + ); + return mementos; + } } @Override @@ -948,7 +970,7 @@ public List getResultList() { @Override public R getSingleResult() { - final List resultList = getResultList(); + final var resultList = getResultList(); if ( resultList == null || resultList.isEmpty() ) { throw new NoResultException( String.format( @@ -971,7 +993,7 @@ else if ( resultList.size() > 1 ) { @Override public R getSingleResultOrNull() { - final List resultList = getResultList(); + final var resultList = getResultList(); if ( resultList == null || resultList.isEmpty() ) { return null; } diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java index e3c422826c52..2d80b8dc30cf 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java +++ b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractCommonQueryContract.java @@ -25,18 +25,14 @@ import org.hibernate.graph.GraphParser; import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.internal.RootGraphImpl; -import org.hibernate.graph.spi.AppliedGraph; import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.jpa.internal.util.ConfigurationHelper; import org.hibernate.jpa.internal.util.FlushModeTypeHelper; -import org.hibernate.metamodel.model.domain.ManagedDomainType; +import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.property.access.spi.BuiltInPropertyAccessStrategies; -import org.hibernate.property.access.spi.Getter; -import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.query.CommonQueryContract; import org.hibernate.query.QueryArgumentException; import org.hibernate.query.QueryFlushMode; -import org.hibernate.query.QueryLogging; import org.hibernate.query.QueryParameter; import org.hibernate.query.TypedParameterValue; import org.hibernate.query.criteria.JpaExpression; @@ -47,7 +43,6 @@ import org.hibernate.query.sqm.tree.expression.SqmLiteral; import org.hibernate.query.sqm.tree.expression.SqmParameter; import org.hibernate.query.sqm.tree.select.SqmSelectStatement; -import org.hibernate.type.BasicType; import org.hibernate.type.BindableType; import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.spi.TypeConfiguration; @@ -93,6 +88,7 @@ import static org.hibernate.jpa.internal.util.ConfigurationHelper.getBoolean; import static org.hibernate.jpa.internal.util.ConfigurationHelper.getCacheMode; import static org.hibernate.jpa.internal.util.ConfigurationHelper.getInteger; +import static org.hibernate.query.QueryLogging.QUERY_MESSAGE_LOGGER; /** * Base implementation of {@link CommonQueryContract}. @@ -126,10 +122,18 @@ public final SessionFactoryImplementor getSessionFactory() { return session.getFactory(); } + public final MappingMetamodelImplementor getMappingMetamodel() { + return session.getFactory().getMappingMetamodel(); + } + public final TypeConfiguration getTypeConfiguration() { return session.getFactory().getTypeConfiguration(); } + protected QueryInterpretationCache getInterpretationCache() { + return session.getFactory().getQueryEngine().getInterpretationCache(); + } + protected final ExceptionConverter getExceptionConverter() { return session.getExceptionConverter(); } @@ -149,30 +153,30 @@ else if ( expression instanceof Parameter ) { } protected int getMaxRows(SqmSelectStatement selectStatement, int size) { - final JpaExpression expression = selectStatement.getFetch(); - if ( expression == null ) { - return -1; + final var fetchExpression = selectStatement.getFetch(); + if ( fetchExpression != null ) { + final var fetchValue = fetchValue( fetchExpression ); + if ( fetchValue != null ) { + // Note that we can never have ties because this is only used when we deduplicate results + return switch ( selectStatement.getFetchClauseType() ) { + case ROWS_ONLY, ROWS_WITH_TIES -> fetchValue.intValue(); + case PERCENT_ONLY, PERCENT_WITH_TIES -> + (int) Math.ceil( (((double) size) * fetchValue.doubleValue()) / 100d ); + }; + } + } + return -1; + } + + private Number fetchValue(JpaExpression expression) { + if ( expression instanceof SqmLiteral ) { + return ((SqmLiteral) expression).getLiteralValue(); + } + else if ( expression instanceof SqmParameter ) { + return getParameterValue( (Parameter) expression ); } else { - final Number fetchValue; - if ( expression instanceof SqmLiteral ) { - fetchValue = ((SqmLiteral) expression).getLiteralValue(); - } - else if ( expression instanceof SqmParameter ) { - fetchValue = getParameterValue( (Parameter) expression ); - if ( fetchValue == null ) { - return -1; - } - } - else { - throw new IllegalArgumentException( "Can't get max rows value from: " + expression ); - } - // Note that we can never have ties because this is only used when we de-duplicate results - return switch ( selectStatement.getFetchClauseType() ) { - case ROWS_ONLY, ROWS_WITH_TIES -> fetchValue.intValue(); - case PERCENT_ONLY, PERCENT_WITH_TIES -> - (int) Math.ceil( (((double) size) * fetchValue.doubleValue()) / 100d ); - }; + throw new IllegalArgumentException( "Can't get max rows value from: " + expression ); } } @@ -191,36 +195,41 @@ public Map getHints() { @SuppressWarnings("deprecation") protected void collectHints(Map hints) { - if ( getQueryOptions().getTimeout() != null ) { - hints.put( HINT_TIMEOUT, getQueryOptions().getTimeout() ); - hints.put( HINT_SPEC_QUERY_TIMEOUT, getQueryOptions().getTimeout() * 1000 ); + final var queryOptions = getQueryOptions(); + + if ( queryOptions.getTimeout() != null ) { + hints.put( HINT_TIMEOUT, queryOptions.getTimeout() ); + hints.put( HINT_SPEC_QUERY_TIMEOUT, queryOptions.getTimeout() * 1000 ); } putIfNotNull( hints, HINT_COMMENT, getComment() ); - putIfNotNull( hints, HINT_FLUSH_MODE, getQueryOptions().getFlushMode() ); - - putIfNotNull( hints, HINT_READONLY, getQueryOptions().isReadOnly() ); - putIfNotNull( hints, HINT_FETCH_SIZE, getQueryOptions().getFetchSize() ); - putIfNotNull( hints, HINT_CACHEABLE, getQueryOptions().isResultCachingEnabled() ); - putIfNotNull( hints, HINT_CACHE_REGION, getQueryOptions().getResultCacheRegionName() ); - putIfNotNull( hints, HINT_CACHE_MODE, getQueryOptions().getCacheMode() ); - putIfNotNull( hints, HINT_QUERY_PLAN_CACHEABLE, getQueryOptions().getQueryPlanCachingEnabled() ); - - putIfNotNull( hints, HINT_SPEC_CACHE_RETRIEVE_MODE, getQueryOptions().getCacheRetrieveMode() ); - putIfNotNull( hints, HINT_JAVAEE_CACHE_RETRIEVE_MODE, getQueryOptions().getCacheRetrieveMode() ); - - putIfNotNull( hints, HINT_SPEC_CACHE_STORE_MODE, getQueryOptions().getCacheStoreMode() ); - putIfNotNull( hints, HINT_JAVAEE_CACHE_STORE_MODE, getQueryOptions().getCacheStoreMode() ); - - final AppliedGraph appliedGraph = getQueryOptions().getAppliedGraph(); - if ( appliedGraph != null && appliedGraph.getSemantic() != null ) { - hints.put( appliedGraph.getSemantic().getJakartaHintName(), appliedGraph.getGraph() ); - hints.put( appliedGraph.getSemantic().getJpaHintName(), appliedGraph.getGraph() ); + putIfNotNull( hints, HINT_FLUSH_MODE, queryOptions.getFlushMode() ); + + putIfNotNull( hints, HINT_READONLY, queryOptions.isReadOnly() ); + putIfNotNull( hints, HINT_FETCH_SIZE, queryOptions.getFetchSize() ); + putIfNotNull( hints, HINT_CACHEABLE, queryOptions.isResultCachingEnabled() ); + putIfNotNull( hints, HINT_CACHE_REGION, queryOptions.getResultCacheRegionName() ); + putIfNotNull( hints, HINT_CACHE_MODE, queryOptions.getCacheMode() ); + putIfNotNull( hints, HINT_QUERY_PLAN_CACHEABLE, queryOptions.getQueryPlanCachingEnabled() ); + + putIfNotNull( hints, HINT_SPEC_CACHE_RETRIEVE_MODE, queryOptions.getCacheRetrieveMode() ); + putIfNotNull( hints, HINT_JAVAEE_CACHE_RETRIEVE_MODE, queryOptions.getCacheRetrieveMode() ); + + putIfNotNull( hints, HINT_SPEC_CACHE_STORE_MODE, queryOptions.getCacheStoreMode() ); + putIfNotNull( hints, HINT_JAVAEE_CACHE_STORE_MODE, queryOptions.getCacheStoreMode() ); + + final var appliedGraph = queryOptions.getAppliedGraph(); + if ( appliedGraph != null ) { + final var semantic = appliedGraph.getSemantic(); + if ( semantic != null ) { + hints.put( semantic.getJakartaHintName(), appliedGraph.getGraph() ); + hints.put( semantic.getJpaHintName(), appliedGraph.getGraph() ); + } } - final LockOptions lockOptions = getLockOptions(); - if ( ! lockOptions.isEmpty() ) { - final LockMode lockMode = lockOptions.getLockMode(); + final var lockOptions = getLockOptions(); + if ( !lockOptions.isEmpty() ) { + final var lockMode = lockOptions.getLockMode(); if ( lockMode != null && lockMode != LockMode.NONE ) { hints.put( HINT_NATIVE_LOCKMODE, lockMode ); } @@ -254,7 +263,7 @@ protected void putIfNotNull(Map hints, String hintName, Object h @Override public CommonQueryContract setHint(String hintName, Object value) { if ( !applyHint( hintName, value ) ) { - QueryLogging.QUERY_MESSAGE_LOGGER.ignoringUnrecognizedQueryHint( hintName ); + QUERY_MESSAGE_LOGGER.ignoringUnrecognizedQueryHint( hintName ); } return this; } @@ -304,7 +313,7 @@ protected final boolean applySelectionHint(String hintName, Object value) { return true; } else { - final MutableQueryOptions queryOptions = getQueryOptions(); + final var queryOptions = getQueryOptions(); switch ( hintName ) { case HINT_READONLY: queryOptions.setReadOnly( getBoolean( value ) ); @@ -328,16 +337,14 @@ protected final boolean applySelectionHint(String hintName, Object value) { DEPRECATION_LOGGER.deprecatedHint( HINT_JAVAEE_CACHE_RETRIEVE_MODE, HINT_SPEC_CACHE_RETRIEVE_MODE ); //fall through to: case HINT_SPEC_CACHE_RETRIEVE_MODE: - final CacheRetrieveMode retrieveMode = - value == null ? null : CacheRetrieveMode.valueOf( value.toString() ); + final var retrieveMode = value == null ? null : CacheRetrieveMode.valueOf( value.toString() ); queryOptions.setCacheRetrieveMode( retrieveMode ); return true; case HINT_JAVAEE_CACHE_STORE_MODE: DEPRECATION_LOGGER.deprecatedHint( HINT_JAVAEE_CACHE_STORE_MODE, HINT_SPEC_CACHE_STORE_MODE ); //fall through to: case HINT_SPEC_CACHE_STORE_MODE: - final CacheStoreMode storeMode = - value == null ? null : CacheStoreMode.valueOf( value.toString() ); + final var storeMode = value == null ? null : CacheStoreMode.valueOf( value.toString() ); queryOptions.setCacheStoreMode( storeMode ); return true; case HINT_JAVAEE_FETCH_GRAPH: @@ -417,8 +424,7 @@ protected void applyGraph(String graphString, GraphSemantic graphSemantic) { .getImportedName( graphString.substring( 0, separatorPosition ).trim() ); final String graphNodes = graphString.substring( separatorPosition + 1, terminatorPosition ); - final RootGraphImpl rootGraph = - new RootGraphImpl<>( null, factory.getJpaMetamodel().entity( entityName ) ); + final var rootGraph = new RootGraphImpl<>( null, factory.getJpaMetamodel().entity( entityName ) ); GraphParser.parseInto( (EntityGraph) rootGraph, graphNodes, getSessionFactory() ); applyGraph( rootGraph, graphSemantic ); } @@ -731,19 +737,19 @@ protected

QueryParameterBinding

locateBinding(int position) { public boolean isBound(Parameter param) { getCheckOpen(); - final QueryParameterImplementor parameter = getParameterMetadata().resolve( param ); + final var parameter = getParameterMetadata().resolve( param ); return parameter != null && getQueryParameterBindings().isBound( parameter ); } public T getParameterValue(Parameter param) { checkOpenNoRollback(); - final QueryParameterImplementor parameter = getParameterMetadata().resolve( param ); + final var parameter = getParameterMetadata().resolve( param ); if ( parameter == null ) { throw new IllegalArgumentException( "The parameter [" + param + "] is not part of this Query" ); } - final QueryParameterBinding binding = getQueryParameterBindings().getBinding( parameter ); + final var binding = getQueryParameterBindings().getBinding( parameter ); if ( binding == null || !binding.isBound() ) { throw new IllegalStateException( "Parameter value not yet bound : " + param.toString() ); } @@ -760,7 +766,7 @@ public T getParameterValue(Parameter param) { public Object getParameterValue(String name) { checkOpenNoRollback(); - final QueryParameterBinding binding = getQueryParameterBindings().getBinding( name ); + final QueryParameterBinding binding = getQueryParameterBindings().getBinding( name ); if ( !binding.isBound() ) { throw new IllegalStateException( "The parameter [" + name + "] has not yet been bound" ); } @@ -776,7 +782,7 @@ public Object getParameterValue(String name) { public Object getParameterValue(int position) { checkOpenNoRollback(); - final QueryParameterBinding binding = getQueryParameterBindings().getBinding( position ); + final QueryParameterBinding binding = getQueryParameterBindings().getBinding( position ); if ( !binding.isBound() ) { throw new IllegalStateException( "The parameter [" + position + "] has not yet been bound" ); } @@ -803,9 +809,9 @@ public CommonQueryContract setParameter(String name, Object value) { return this; } - private boolean multipleBinding(QueryParameter param, Object value){ - if ( param.allowsMultiValuedBinding() ) { - final Type hibernateType = param.getHibernateType(); + private boolean multipleBinding(QueryParameter parameter, Object value){ + if ( parameter.allowsMultiValuedBinding() ) { + final var hibernateType = parameter.getHibernateType(); if ( hibernateType == null || hibernateType instanceof NullSqmExpressible || isInstance( hibernateType, value ) ) { @@ -835,7 +841,7 @@ private NodeBuilder getNodeuilder() { @Override public

CommonQueryContract setParameter(String name, P value, Class

javaType) { - final JavaType

javaDescriptor = getJavaType( javaType ); + final var javaDescriptor = getJavaType( javaType ); if ( javaDescriptor == null ) { setParameter( name, value ); } @@ -882,7 +888,7 @@ private boolean isRegisteredAsBasicType(Class valueClass) { @Override public

CommonQueryContract setParameter(int position, P value, Class

javaType) { - final JavaType

javaDescriptor = getJavaType( javaType ); + final var javaDescriptor = getJavaType( javaType ); if ( javaDescriptor == null ) { setParameter( position, value ); } @@ -912,7 +918,7 @@ public

CommonQueryContract setParameter(QueryParameter

parameter, P value @Override public

CommonQueryContract setParameter(QueryParameter

parameter, P value, Class

javaType) { - final JavaType

javaDescriptor = getJavaType( javaType ); + final var javaDescriptor = getJavaType( javaType ); if ( javaDescriptor == null ) { setParameter( parameter, value ); } @@ -932,8 +938,8 @@ public

CommonQueryContract setParameter(QueryParameter

parameter, P value @Override public

CommonQueryContract setParameter(Parameter

parameter, P value) { if ( value instanceof TypedParameterValue typedParameterValue ) { - final Class

parameterType = parameter.getParameterType(); - final BindableType type = typedParameterValue.type(); + final var parameterType = parameter.getParameterType(); + final var type = typedParameterValue.type(); if ( type == null ) { throw new IllegalArgumentException( "TypedParameterValue has no type" ); } @@ -942,7 +948,7 @@ public

CommonQueryContract setParameter(Parameter

parameter, P value) { parameterType, typedParameterValue.value() ); } @SuppressWarnings("unchecked") // safe, because we just checked - final TypedParameterValue

typedValue = (TypedParameterValue

) value; + final var typedValue = (TypedParameterValue

) value; setParameter( parameter, typedValue.value(), typedValue.type() ); } else { @@ -1036,7 +1042,7 @@ public CommonQueryContract setParameterList(String name, Object[] values) { @Override public

CommonQueryContract setParameterList(String name, P[] values, Class

javaType) { - final JavaType

javaDescriptor = getJavaType( javaType ); + final var javaDescriptor = getJavaType( javaType ); if ( javaDescriptor == null ) { setParameterList( name, values ); } @@ -1059,7 +1065,7 @@ public CommonQueryContract setParameterList(int position, @SuppressWarnings("raw @Override public

CommonQueryContract setParameterList(int position, Collection values, Class

javaType) { - final JavaType

javaDescriptor = getJavaType( javaType ); + final var javaDescriptor = getJavaType( javaType ); if ( javaDescriptor == null ) { setParameterList( position, values ); } @@ -1070,14 +1076,14 @@ public

CommonQueryContract setParameterList(int position, Collection Type

getParamType(Class

javaType) { - final BasicType

basicType = + final var basicType = getTypeConfiguration() .standardBasicTypeForJavaType( javaType ); if ( basicType != null ) { return basicType; } else { - final ManagedDomainType

managedDomainType = + final var managedDomainType = getSessionFactory().getJpaMetamodel() .managedType( javaType ); if ( managedDomainType != null ) { @@ -1103,7 +1109,7 @@ public CommonQueryContract setParameterList(int position, Object[] values) { @Override public

CommonQueryContract setParameterList(int position, P[] values, Class

javaType) { - final JavaType

javaDescriptor = getJavaType( javaType ); + final var javaDescriptor = getJavaType( javaType ); if ( javaDescriptor == null ) { setParameterList( position, values ); } @@ -1129,14 +1135,13 @@ public

CommonQueryContract setParameterList(QueryParameter

parameter, Col @Override public

CommonQueryContract setParameterList(QueryParameter

parameter, Collection values, Class

javaType) { - final JavaType

javaDescriptor = getJavaType( javaType ); + final var javaDescriptor = getJavaType( javaType ); if ( javaDescriptor == null ) { setParameterList( parameter, values ); } else { setParameterList( parameter, values, getParamType( javaType ) ); } - return this; } @@ -1154,7 +1159,7 @@ public

CommonQueryContract setParameterList(QueryParameter

parameter, P[] @Override public

CommonQueryContract setParameterList(QueryParameter

parameter, P[] values, Class

javaType) { - final JavaType

javaDescriptor = getJavaType( javaType ); + final var javaDescriptor = getJavaType( javaType ); if ( javaDescriptor == null ) { setParameterList( parameter, values ); } @@ -1212,23 +1217,23 @@ protected Type determineType(String namedParam, Class retTyp @Override public CommonQueryContract setProperties(Object bean) { - final Class clazz = bean.getClass(); + final var beanClass = bean.getClass(); for ( String paramName : getParameterMetadata().getNamedParameterNames() ) { try { - final PropertyAccess propertyAccess = + final var getter = BuiltInPropertyAccessStrategies.BASIC.getStrategy() - .buildPropertyAccess( clazz, paramName, true ); - final Getter getter = propertyAccess.getGetter(); - final Class retType = getter.getReturnTypeClass(); + .buildPropertyAccess( beanClass, paramName, true ) + .getGetter(); + final var returnType = getter.getReturnTypeClass(); final Object object = getter.get( bean ); - if ( Collection.class.isAssignableFrom( retType ) ) { + if ( Collection.class.isAssignableFrom( returnType ) ) { setParameterList( paramName, (Collection) object ); } - else if ( retType.isArray() ) { + else if ( returnType.isArray() ) { setParameterList( paramName, (Object[]) object ); } else { - setParameter( paramName, object, determineType( paramName, retType ) ); + setParameter( paramName, object, determineType( paramName, returnType ) ); } } catch (PropertyNotFoundException pnfe) { diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractQuery.java b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractQuery.java index 97bd9d3e8e4f..0ad0de8552f0 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractQuery.java +++ b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractQuery.java @@ -337,32 +337,35 @@ public Set getSupportedHints() { @Override protected void collectHints(Map hints) { - if ( getQueryOptions().getTimeout() != null ) { - hints.put( HINT_TIMEOUT, getQueryOptions().getTimeout() ); - hints.put( HINT_SPEC_QUERY_TIMEOUT, getQueryOptions().getTimeout() * 1000 ); - hints.put( HINT_JAVAEE_QUERY_TIMEOUT, getQueryOptions().getTimeout() * 1000 ); + final var queryOptions = getQueryOptions(); + final var lockOptions = getLockOptions(); + + if ( queryOptions.getTimeout() != null ) { + hints.put( HINT_TIMEOUT, queryOptions.getTimeout() ); + hints.put( HINT_SPEC_QUERY_TIMEOUT, queryOptions.getTimeout() * 1000 ); + hints.put( HINT_JAVAEE_QUERY_TIMEOUT, queryOptions.getTimeout() * 1000 ); } - if ( getLockOptions().getTimeout().milliseconds() != Timeouts.WAIT_FOREVER_MILLI ) { - hints.put( HINT_SPEC_LOCK_TIMEOUT, getLockOptions().getTimeOut() ); - hints.put( HINT_JAVAEE_LOCK_TIMEOUT, getLockOptions().getTimeOut() ); + if ( lockOptions.getTimeout().milliseconds() != Timeouts.WAIT_FOREVER_MILLI ) { + hints.put( HINT_SPEC_LOCK_TIMEOUT, lockOptions.getTimeOut() ); + hints.put( HINT_JAVAEE_LOCK_TIMEOUT, lockOptions.getTimeOut() ); } - if ( getLockOptions().getLockScope() == PessimisticLockScope.EXTENDED ) { - hints.put( HINT_SPEC_LOCK_SCOPE, getLockOptions().getLockScope() ); - hints.put( HINT_JAVAEE_LOCK_SCOPE, getLockOptions().getLockScope() ); + if ( lockOptions.getLockScope() == PessimisticLockScope.EXTENDED ) { + hints.put( HINT_SPEC_LOCK_SCOPE, lockOptions.getLockScope() ); + hints.put( HINT_JAVAEE_LOCK_SCOPE, lockOptions.getLockScope() ); } putIfNotNull( hints, HINT_COMMENT, getComment() ); - putIfNotNull( hints, HINT_FETCH_SIZE, getQueryOptions().getFetchSize() ); - putIfNotNull( hints, HINT_FLUSH_MODE, getQueryOptions().getFlushMode() ); + putIfNotNull( hints, HINT_FETCH_SIZE, queryOptions.getFetchSize() ); + putIfNotNull( hints, HINT_FLUSH_MODE, queryOptions.getFlushMode() ); if ( getCacheMode() != null ) { putIfNotNull( hints, HINT_CACHE_MODE, getCacheMode() ); - putIfNotNull( hints, HINT_SPEC_CACHE_RETRIEVE_MODE, getQueryOptions().getCacheRetrieveMode() ); - putIfNotNull( hints, HINT_SPEC_CACHE_STORE_MODE, getQueryOptions().getCacheStoreMode() ); - putIfNotNull( hints, HINT_JAVAEE_CACHE_RETRIEVE_MODE, getQueryOptions().getCacheRetrieveMode() ); - putIfNotNull( hints, HINT_JAVAEE_CACHE_STORE_MODE, getQueryOptions().getCacheStoreMode() ); + putIfNotNull( hints, HINT_SPEC_CACHE_RETRIEVE_MODE, queryOptions.getCacheRetrieveMode() ); + putIfNotNull( hints, HINT_SPEC_CACHE_STORE_MODE, queryOptions.getCacheStoreMode() ); + putIfNotNull( hints, HINT_JAVAEE_CACHE_RETRIEVE_MODE, queryOptions.getCacheRetrieveMode() ); + putIfNotNull( hints, HINT_JAVAEE_CACHE_STORE_MODE, queryOptions.getCacheStoreMode() ); } if ( isCacheable() ) { diff --git a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractSelectionQuery.java b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractSelectionQuery.java index e6f0fd741e97..b6d2f7cc540f 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractSelectionQuery.java +++ b/hibernate-core/src/main/java/org/hibernate/query/spi/AbstractSelectionQuery.java @@ -12,7 +12,6 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Spliterator; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -33,7 +32,6 @@ import org.hibernate.UnknownProfileException; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.graph.GraphSemantic; -import org.hibernate.graph.spi.AppliedGraph; import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.jpa.internal.util.FlushModeTypeHelper; import org.hibernate.jpa.internal.util.LockModeTypeHelper; @@ -55,6 +53,7 @@ import jakarta.persistence.TemporalType; import jakarta.persistence.metamodel.Type; +import static java.util.Spliterator.NONNULL; import static java.util.Spliterators.spliteratorUnknownSize; import static org.hibernate.CacheMode.fromJpaModes; import static org.hibernate.cfg.AvailableSettings.JAKARTA_SHARED_CACHE_RETRIEVE_MODE; @@ -168,7 +167,7 @@ public List list() { protected HashSet beforeQueryHandlingFetchProfiles() { beforeQuery(); - final MutableQueryOptions options = getQueryOptions(); + final var options = getQueryOptions(); return getSession().getLoadQueryInfluencers() .adjustFetchProfiles( options.getDisabledFetchProfiles(), options.getEnabledFetchProfiles() ); } @@ -176,8 +175,8 @@ protected HashSet beforeQueryHandlingFetchProfiles() { protected void beforeQuery() { getQueryParameterBindings().validate(); - final SharedSessionContractImplementor session = getSession(); - final MutableQueryOptions options = getQueryOptions(); + final var session = getSession(); + final var options = getQueryOptions(); session.prepareForQueryExecution( requiresTxn( options.getLockOptions().getLockMode() ) ); prepareForExecution(); @@ -185,13 +184,13 @@ protected void beforeQuery() { assert sessionFlushMode == null; assert sessionCacheMode == null; - final FlushMode effectiveFlushMode = getQueryOptions().getFlushMode(); + final var effectiveFlushMode = getQueryOptions().getFlushMode(); if ( effectiveFlushMode != null && session instanceof SessionImplementor statefulSession ) { sessionFlushMode = statefulSession.getHibernateFlushMode(); statefulSession.setHibernateFlushMode( effectiveFlushMode ); } - final CacheMode effectiveCacheMode = getCacheMode(); + final var effectiveCacheMode = getCacheMode(); if ( effectiveCacheMode != null ) { sessionCacheMode = session.getCacheMode(); session.setCacheMode( effectiveCacheMode ); @@ -217,7 +216,7 @@ private void resetFetchProfiles(HashSet fetchProfiles) { protected void afterQuery(boolean success) { afterQuery(); - final SharedSessionContractImplementor session = getSession(); + final var session = getSession(); if ( !session.isTransactionInProgress() ) { session.getJdbcCoordinator().getLogicalConnection().afterTransaction(); } @@ -249,7 +248,7 @@ public ScrollableResultsImplementor scroll() { @Override public ScrollableResultsImplementor scroll(ScrollMode scrollMode) { - final HashSet fetchProfiles = beforeQueryHandlingFetchProfiles(); + final var fetchProfiles = beforeQueryHandlingFetchProfiles(); try { return doScroll( scrollMode ); } @@ -268,8 +267,7 @@ public Stream getResultStream() { @Override public Stream stream() { final ScrollableResults results = scroll( ScrollMode.FORWARD_ONLY ); - final Spliterator spliterator = - spliteratorUnknownSize( new ScrollableResultsIterator<>( results ), Spliterator.NONNULL ); + final var spliterator = spliteratorUnknownSize( new ScrollableResultsIterator<>( results ), NONNULL ); return StreamSupport.stream( spliterator, false ).onClose( results::close ); } @@ -392,7 +390,7 @@ public SelectionQuery setEntityGraph(EntityGraph graph, GraphSeman @Override public SelectionQuery enableFetchProfile(String profileName) { - if ( this.getSessionFactory().containsFetchProfileDefinition( profileName ) ) { + if ( getSessionFactory().containsFetchProfileDefinition( profileName ) ) { getQueryOptions().enableFetchProfile( profileName ); return this; } @@ -491,27 +489,32 @@ protected void collectHints(Map hints) { putIfNotNull( hints, HINT_FETCH_SIZE, getFetchSize() ); + final var queryOptions = getQueryOptions(); + if ( isCacheable() ) { hints.put( HINT_CACHEABLE, true ); putIfNotNull( hints, HINT_CACHE_REGION, getCacheRegion() ); - putIfNotNull( hints, HINT_CACHE_MODE, getCacheMode() ); - putIfNotNull( hints, JAKARTA_SHARED_CACHE_RETRIEVE_MODE, getQueryOptions().getCacheRetrieveMode() ); - putIfNotNull( hints, JAKARTA_SHARED_CACHE_STORE_MODE, getQueryOptions().getCacheStoreMode() ); + putIfNotNull( hints, JAKARTA_SHARED_CACHE_RETRIEVE_MODE, queryOptions.getCacheRetrieveMode() ); + putIfNotNull( hints, JAKARTA_SHARED_CACHE_STORE_MODE, queryOptions.getCacheStoreMode() ); //noinspection deprecation - putIfNotNull( hints, JPA_SHARED_CACHE_RETRIEVE_MODE, getQueryOptions().getCacheRetrieveMode() ); + putIfNotNull( hints, JPA_SHARED_CACHE_RETRIEVE_MODE, queryOptions.getCacheRetrieveMode() ); //noinspection deprecation - putIfNotNull( hints, JPA_SHARED_CACHE_STORE_MODE, getQueryOptions().getCacheStoreMode() ); + putIfNotNull( hints, JPA_SHARED_CACHE_STORE_MODE, queryOptions.getCacheStoreMode() ); } - final AppliedGraph appliedGraph = getQueryOptions().getAppliedGraph(); - if ( appliedGraph != null && appliedGraph.getSemantic() != null ) { - hints.put( appliedGraph.getSemantic().getJakartaHintName(), appliedGraph ); - hints.put( appliedGraph.getSemantic().getJpaHintName(), appliedGraph ); + final var appliedGraph = queryOptions.getAppliedGraph(); + if ( appliedGraph != null ) { + final var semantic = appliedGraph.getSemantic(); + if ( semantic != null ) { + hints.put( semantic.getJakartaHintName(), appliedGraph ); + hints.put( semantic.getJpaHintName(), appliedGraph ); + } } - putIfNotNull( hints, HINT_FOLLOW_ON_LOCKING, getQueryOptions().getLockOptions().getFollowOnLocking() ); - putIfNotNull( hints, HINT_FOLLOW_ON_STRATEGY, getQueryOptions().getLockOptions().getFollowOnStrategy() ); + final var lockOptions = queryOptions.getLockOptions(); + putIfNotNull( hints, HINT_FOLLOW_ON_LOCKING, lockOptions.getFollowOnLocking() ); + putIfNotNull( hints, HINT_FOLLOW_ON_STRATEGY, lockOptions.getFollowOnStrategy() ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/sql/internal/NativeQueryImpl.java b/hibernate-core/src/main/java/org/hibernate/query/sql/internal/NativeQueryImpl.java index dd66e3708035..a02c4338bb76 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sql/internal/NativeQueryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sql/internal/NativeQueryImpl.java @@ -24,8 +24,6 @@ import org.hibernate.CacheMode; import org.hibernate.FlushMode; import org.hibernate.Locking; -import org.hibernate.dialect.pagination.LimitHandler; -import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.jpa.spi.NativeQueryArrayTransformer; @@ -34,7 +32,6 @@ import org.hibernate.jpa.spi.NativeQueryMapTransformer; import org.hibernate.metamodel.mapping.EntityAssociationMapping; import org.hibernate.metamodel.mapping.EntityMappingType; -import org.hibernate.metamodel.mapping.MappingType; import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping; @@ -45,7 +42,6 @@ import org.hibernate.ScrollMode; import org.hibernate.dialect.Dialect; import org.hibernate.engine.query.spi.NativeQueryInterpreter; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.RootGraph; @@ -71,7 +67,6 @@ import org.hibernate.query.results.ResultBuilder; import org.hibernate.query.results.ResultSetMapping; import org.hibernate.query.results.internal.ResultSetMappingImpl; -import org.hibernate.query.results.internal.dynamic.DynamicFetchBuilderLegacy; import org.hibernate.query.results.internal.dynamic.DynamicResultBuilderBasicStandard; import org.hibernate.query.results.internal.dynamic.DynamicResultBuilderEntityCalculated; import org.hibernate.query.results.internal.dynamic.DynamicResultBuilderEntityStandard; @@ -87,7 +82,6 @@ import org.hibernate.query.spi.QueryImplementor; import org.hibernate.query.spi.QueryInterpretationCache; import org.hibernate.query.spi.QueryOptions; -import org.hibernate.query.spi.QueryParameterBinding; import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.query.spi.QueryParameterImplementor; import org.hibernate.query.spi.ScrollableResultsImplementor; @@ -100,7 +94,6 @@ import org.hibernate.query.sql.spi.ParameterInterpretation; import org.hibernate.query.sql.spi.ParameterOccurrence; import org.hibernate.query.sql.spi.SelectInterpretationsKey; -import org.hibernate.sql.ast.internal.ParameterMarkerStrategyStandard; import org.hibernate.sql.ast.spi.ParameterMarkerStrategy; import org.hibernate.sql.exec.internal.CallbackImpl; import org.hibernate.sql.exec.spi.Callback; @@ -140,6 +133,7 @@ import static org.hibernate.query.results.internal.Builders.resultClassBuilder; import static org.hibernate.query.results.ResultSetMapping.resolveResultSetMapping; import static org.hibernate.query.sqm.internal.SqmUtil.isResultTypeAlwaysAllowed; +import static org.hibernate.sql.ast.internal.ParameterMarkerStrategyStandard.isStandardRenderer; /** * @author Steve Ebersole @@ -178,7 +172,7 @@ public NativeQueryImpl(NamedNativeQueryMemento memento, SharedSessionContract () -> buildResultSetMapping( getResultSetMappingName( memento ), false, session ), (resultSetMapping, querySpaceConsumer, context ) -> { if ( memento.getResultMappingName() != null ) { - final NamedResultSetMappingMemento resultSetMappingMemento = + final var resultSetMappingMemento = getNamedObjectRepository( session ) .getResultSetMappingMemento( memento.getResultMappingName() ); if ( resultSetMappingMemento != null ) { @@ -215,7 +209,7 @@ public NativeQueryImpl( }, (resultSetMapping, querySpaceConsumer, context) -> { if ( memento.getResultMappingName() != null ) { - final NamedResultSetMappingMemento resultSetMappingMemento = + final var resultSetMappingMemento = getNamedObjectRepository( session ) .getResultSetMappingMemento( memento.getResultMappingName() ); if ( resultSetMappingMemento != null ) { @@ -248,7 +242,7 @@ public NativeQueryImpl( memento, () -> buildResultSetMapping( resultSetMappingName, false, session ), (resultSetMapping, querySpaceConsumer, context) -> { - final NamedResultSetMappingMemento mappingMemento = + final var mappingMemento = getNamedObjectRepository( session ) .getResultSetMappingMemento( resultSetMappingName ); assert mappingMemento != null; @@ -271,8 +265,7 @@ private NativeQueryImpl( originalSqlString = memento.getOriginalSqlString(); querySpaces = new HashSet<>(); - final ParameterInterpretation parameterInterpretation = - resolveParameterInterpretation( originalSqlString, session ); + final var parameterInterpretation = resolveParameterInterpretation( originalSqlString, session ); sqlString = parameterInterpretation.getAdjustedSqlString(); parameterMetadata = parameterInterpretation.toParameterMetadata( session ); parameterOccurrences = parameterInterpretation.getOrderedParameterOccurrences(); @@ -297,7 +290,7 @@ public NativeQueryImpl( originalSqlString = sql; querySpaces = new HashSet<>(); - final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( sql, session ); + final var parameterInterpretation = resolveParameterInterpretation( sql, session ); sqlString = parameterInterpretation.getAdjustedSqlString(); parameterMetadata = parameterInterpretation.toParameterMetadata( session ); parameterOccurrences = parameterInterpretation.getOrderedParameterOccurrences(); @@ -316,7 +309,7 @@ public NativeQueryImpl(String sql, @Nullable Class resultClass, SharedSession originalSqlString = sql; querySpaces = new HashSet<>(); - final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( sql, session ); + final var parameterInterpretation = resolveParameterInterpretation( sql, session ); sqlString = parameterInterpretation.getAdjustedSqlString(); parameterMetadata = parameterInterpretation.toParameterMetadata( session ); parameterOccurrences = parameterInterpretation.getOrderedParameterOccurrences(); @@ -356,8 +349,7 @@ private void checkResultType(Class resultType, ResultSetMapping resultSetMapp } break; case 1: - final Class actualResultJavaType = - resultSetMapping.getResultBuilders().get( 0 ).getJavaType(); + final var actualResultJavaType = resultSetMapping.getResultBuilders().get( 0 ).getJavaType(); if ( actualResultJavaType != null && !resultType.isAssignableFrom( actualResultJavaType ) ) { throw buildIncompatibleException( resultType, actualResultJavaType ); } @@ -395,7 +387,7 @@ private boolean validConstructorFoundForResultType(Class resultType, ResultSe } private static boolean constructorParameterMatches(ResultBuilder resultBuilder, Class paramType) { - final Class parameterClass = + final var parameterClass = paramType.isPrimitive() ? getDescriptorByPrimitiveType( paramType ).getWrapperClass() : paramType; @@ -403,7 +395,7 @@ private static boolean constructorParameterMatches(ResultBuilder resultBuilder, } protected void setTupleTransformerForResultType(Class resultClass) { - final TupleTransformer tupleTransformer = determineTupleTransformerForResultType( resultClass ); + final var tupleTransformer = determineTupleTransformerForResultType( resultClass ); if ( tupleTransformer != null ) { setTupleTransformer( tupleTransformer ); } @@ -490,15 +482,12 @@ private ParameterInterpretation resolveParameterInterpretation( String sqlString, SharedSessionContractImplementor session) { return getInterpretationCache( session ) .resolveNativeQueryParameters( sqlString, - s -> parameterInterpretation( sqlString, session ) ); + s -> parameterInterpretation( sqlString ) ); } - private static ParameterInterpretationImpl parameterInterpretation( - String sqlString, SharedSessionContractImplementor session) { - final ParameterRecognizerImpl parameterRecognizer = new ParameterRecognizerImpl(); - session.getFactory().getServiceRegistry() - .requireService( NativeQueryInterpreter.class ) - .recognizeParameters( sqlString, parameterRecognizer ); + private ParameterInterpretationImpl parameterInterpretation(String sqlString) { + final var parameterRecognizer = new ParameterRecognizerImpl(); + getNativeQueryInterpreter().recognizeParameters( sqlString, parameterRecognizer ); return new ParameterInterpretationImpl( parameterRecognizer ); } @@ -512,7 +501,7 @@ protected void applyOptions(NamedNativeQueryMemento memento) { setFirstResult( memento.getFirstResult() ); } - final Set mementoQuerySpaces = memento.getQuerySpaces(); + final var mementoQuerySpaces = memento.getQuerySpaces(); if ( mementoQuerySpaces != null ) { querySpaces = makeCopy( mementoQuerySpaces ); } @@ -726,7 +715,7 @@ private boolean startsWithSelect() { @Override protected void prepareForExecution() { - final Collection spaces = getSynchronizedQuerySpaces(); + final var spaces = getSynchronizedQuerySpaces(); if ( spaces == null || spaces.isEmpty() ) { // We need to flush. The query itself is not required to execute in a // transaction; if there is no transaction, the flush would throw a @@ -745,7 +734,7 @@ protected void prepareForExecution() { private boolean shouldFlush() { if ( getSession().isTransactionInProgress() ) { - final FlushMode flushMode = getQueryOptions().getFlushMode(); + final var flushMode = getQueryOptions().getFlushMode(); return switch ( flushMode == null ? getSession().getHibernateFlushMode() : flushMode ) { // The JPA spec requires that we auto-flush before native queries case AUTO -> getSessionFactory().getSessionFactoryOptions().isJpaBootstrap(); @@ -765,7 +754,7 @@ protected List doList() { @Override public long getResultCount() { - final DelegatingDomainQueryExecutionContext context = new DelegatingDomainQueryExecutionContext(this) { + final var context = new DelegatingDomainQueryExecutionContext(this) { @Override public QueryOptions getQueryOptions() { return QueryOptions.NONE; @@ -780,45 +769,58 @@ public KeyedResultList getKeyedResultList(KeyedPage page) { } protected SelectQueryPlan resolveSelectQueryPlan() { - final ResultSetMapping mapping; - if ( resultType != null && resultSetMapping.isDynamic() && resultSetMapping.getNumberOfResultBuilders() == 0 ) { - final SessionFactoryImplementor sessionFactory = getSessionFactory(); - mapping = ResultSetMapping.resolveResultSetMapping( originalSqlString, true, sessionFactory ); - if ( sessionFactory.getMappingMetamodel().isEntityClass( resultType ) ) { - mapping.addResultBuilder( - Builders.entityCalculated( unqualify( resultType.getName() ), resultType.getName(), - LockMode.READ, sessionFactory ) ); - } - else if ( !isResultTypeAlwaysAllowed( resultType ) - && (!isClass( resultType ) || hasJavaTypeDescriptor( resultType )) ) { - mapping.addResultBuilder( Builders.resultClassBuilder( resultType, sessionFactory.getMappingMetamodel() ) ); - } + final var mapping = resultSetMapping(); + checkResultType( resultType, mapping ); + final int parameterStartPosition = parameterStartPosition(); + if ( isCacheableQuery() ) { + return getInterpretationCache().resolveSelectQueryPlan( + selectInterpretationsKey( mapping, parameterStartPosition ), + key -> createQueryPlan( key.getResultSetMapping(), key.getStartPosition() ) + ); } else { - mapping = resultSetMapping; + return createQueryPlan( mapping, parameterStartPosition ); } - checkResultType( resultType, mapping ); - int parameterStartPosition = 1; - final JdbcServices jdbcServices = getSessionFactory().getJdbcServices(); - if ( !ParameterMarkerStrategyStandard.isStandardRenderer( jdbcServices.getParameterMarkerStrategy() ) - && hasLimit( getQueryOptions().getLimit() ) ) { - final LimitHandler limitHandler = jdbcServices.getDialect().getLimitHandler(); + } + + private int parameterStartPosition() { + final var jdbcServices = getSessionFactory().getJdbcServices(); + if ( !isStandardRenderer( jdbcServices.getParameterMarkerStrategy() ) + && hasLimit( getQueryOptions().getLimit() ) ) { + final var limitHandler = jdbcServices.getDialect().getLimitHandler(); if ( limitHandler.processSqlMutatesState() ) { limitHandler.processSql( sqlString, -1, null, getQueryOptions() ); } // A non-standard parameter marker strategy is in use, and the limit handler wants to bind parameters // before the main parameters. This requires recording the start position in the cache key // because the generated SQL depends on this information - parameterStartPosition = limitHandler.getParameterPositionStart( getQueryOptions().getLimit() ); + return limitHandler.getParameterPositionStart( getQueryOptions().getLimit() ); } - if ( isCacheableQuery() ) { - return getInterpretationCache().resolveSelectQueryPlan( - selectInterpretationsKey( mapping, parameterStartPosition ), - key -> createQueryPlan( key.getResultSetMapping(), key.getStartPosition() ) - ); + else { + return 1; + } + } + + private ResultSetMapping resultSetMapping() { + if ( resultType != null + && resultSetMapping.isDynamic() + && resultSetMapping.getNumberOfResultBuilders() == 0 ) { + final var sessionFactory = getSessionFactory(); + final var mapping = resolveResultSetMapping( originalSqlString, true, sessionFactory ); + final var metamodel = getMappingMetamodel(); + if ( metamodel.isEntityClass( resultType ) ) { + mapping.addResultBuilder( + Builders.entityCalculated( unqualify( resultType.getName() ), resultType.getName(), + LockMode.READ, sessionFactory ) ); + } + else if ( !isResultTypeAlwaysAllowed( resultType ) + && (!isClass( resultType ) || hasJavaTypeDescriptor( resultType )) ) { + mapping.addResultBuilder( Builders.resultClassBuilder( resultType, metamodel ) ); + } + return mapping; } else { - return createQueryPlan( mapping, parameterStartPosition ); + return resultSetMapping; } } @@ -902,22 +904,25 @@ protected String expandParameterLists(int parameterStartPosition) { } // HHH-1123 // Some DBs limit number of IN expressions. For now, warn... - final SessionFactoryImplementor factory = getSessionFactory(); - final Dialect dialect = factory.getJdbcServices().getDialect(); + final var factory = getSessionFactory(); + final var dialect = factory.getJdbcServices().getDialect(); final boolean paddingEnabled = factory.getSessionFactoryOptions().inClauseParameterPaddingEnabled(); final int inExprLimit = dialect.getInExpressionCountLimit(); - final ParameterMarkerStrategy parameterMarkerStrategy = factory.getJdbcServices().getParameterMarkerStrategy(); - final boolean needsMarker = !ParameterMarkerStrategyStandard.isStandardRenderer( parameterMarkerStrategy ); + final var parameterMarkerStrategy = factory.getJdbcServices().getParameterMarkerStrategy(); + final boolean needsMarker = !isStandardRenderer( parameterMarkerStrategy ); - StringBuilder sql = !needsMarker ? null - : new StringBuilder( sqlString.length() + parameterOccurrences.size() * 10 ).append( sqlString ); + var sql = + needsMarker + ? new StringBuilder( sqlString.length() + parameterOccurrences.size() * 10 ) + .append( sqlString ) + : null; // Handle parameter lists int offset = 0; int parameterPosition = parameterStartPosition; - for ( ParameterOccurrence occurrence : parameterOccurrences ) { - final QueryParameterImplementor queryParameter = occurrence.parameter(); - final QueryParameterBinding binding = parameterBindings.getBinding( queryParameter ); + for ( var occurrence : parameterOccurrences ) { + final var queryParameter = occurrence.parameter(); + final var binding = parameterBindings.getBinding( queryParameter ); if ( binding.isMultiValued() ) { final int bindValueCount = binding.getBindValues().size(); logTooManyExpressions( inExprLimit, bindValueCount, dialect, queryParameter ); @@ -930,8 +935,8 @@ protected String expandParameterLists(int parameterStartPosition) { // placeholder is already enclosed in parentheses... if ( bindValueCount != 1 || !isEnclosedInParens ) { if ( sql == null ) { - sql = new StringBuilder( sqlString.length() + 20 ); - sql.append( sqlString ); + sql = new StringBuilder( sqlString.length() + 20 ) + .append( sqlString ); } final int bindValueMaxCount = determineBindValueMaxCount( paddingEnabled, inExprLimit, bindValueCount ); @@ -1111,14 +1116,14 @@ private BasicTypeRegistry getBasicTypeRegistry() { return getTypeConfiguration().getBasicTypeRegistry(); } - private QueryInterpretationCache getInterpretationCache() { + protected QueryInterpretationCache getInterpretationCache() { return getInterpretationCache( getSession() ); } private NonSelectQueryPlan resolveNonSelectQueryPlan() { NonSelectQueryPlan queryPlan = null; - final QueryInterpretationCache.Key cacheKey = generateNonSelectInterpretationsKey(); + final var cacheKey = generateNonSelectInterpretationsKey(); if ( cacheKey != null ) { queryPlan = getInterpretationCache().getNonSelectQueryPlan( cacheKey ); } @@ -1176,12 +1181,9 @@ public NativeQueryImplementor addScalar(String columnAlias, @SuppressWarnings public NativeQueryImplementor addScalar(String columnAlias, @SuppressWarnings("rawtypes") Class javaType) { @SuppressWarnings("unchecked") final BasicType basicType = getBasicTypeRegistry().getRegisteredType( javaType ); - if ( basicType != null ) { - return registerBuilder( Builders.scalar( columnAlias, basicType ) ); - } - else { - return registerBuilder( Builders.scalar( columnAlias, javaType, getSessionFactory() ) ); - } + return basicType != null + ? registerBuilder( Builders.scalar( columnAlias, basicType ) ) + : registerBuilder( Builders.scalar( columnAlias, javaType, getSessionFactory() ) ); } @Override @@ -1253,8 +1255,7 @@ public NativeQueryImplementor addAttributeResult( @Override public DynamicResultBuilderEntityStandard addRoot(String tableAlias, String entityName) { - final DynamicResultBuilderEntityStandard resultBuilder = - Builders.entity( tableAlias, entityName, getSessionFactory() ); + final var resultBuilder = Builders.entity( tableAlias, entityName, getSessionFactory() ); resultSetMapping.addResultBuilder( resultBuilder ); entityMappingTypeByTableAlias.put( tableAlias, resultBuilder.getEntityMapping() ); return resultBuilder; @@ -1272,8 +1273,7 @@ public NativeQueryImplementor addEntity(String entityName) { @Override public NativeQueryImplementor addEntity(String tableAlias, String entityName) { - final DynamicResultBuilderEntityCalculated builder = - Builders.entityCalculated( tableAlias, entityName, getSessionFactory() ); + final var builder = Builders.entityCalculated( tableAlias, entityName, getSessionFactory() ); entityMappingTypeByTableAlias.put( tableAlias, builder.getEntityMapping() ); registerBuilder( builder ); return this; @@ -1281,8 +1281,7 @@ public NativeQueryImplementor addEntity(String tableAlias, String entityName) @Override public NativeQueryImplementor addEntity(String tableAlias, String entityName, LockMode lockMode) { - final DynamicResultBuilderEntityCalculated builder = - Builders.entityCalculated( tableAlias, entityName, lockMode, getSessionFactory() ); + final var builder = Builders.entityCalculated( tableAlias, entityName, lockMode, getSessionFactory() ); entityMappingTypeByTableAlias.put( tableAlias, builder.getEntityMapping() ); registerBuilder( builder ); return this; @@ -1310,16 +1309,16 @@ public NativeQueryImplementor addEntity(String tableAlias, @SuppressWarnings( @Override public FetchReturn addFetch(String tableAlias, String ownerTableAlias, String joinPropertyName) { - final ModelPart subPart = entityMappingTypeByTableAlias.get( ownerTableAlias ).findSubPart( joinPropertyName ); + final var subPart = entityMappingTypeByTableAlias.get( ownerTableAlias ).findSubPart( joinPropertyName ); addEntityMappingType( tableAlias, subPart ); - final DynamicFetchBuilderLegacy fetchBuilder = Builders.fetch( tableAlias, ownerTableAlias, (Fetchable) subPart ); + final var fetchBuilder = Builders.fetch( tableAlias, ownerTableAlias, (Fetchable) subPart ); resultSetMapping.addLegacyFetchBuilder( fetchBuilder ); return fetchBuilder; } private void addEntityMappingType(String tableAlias, ModelPart part) { if ( part instanceof PluralAttributeMapping pluralAttributeMapping ) { - final MappingType partMappingType = pluralAttributeMapping.getElementDescriptor().getPartMappingType(); + final var partMappingType = pluralAttributeMapping.getElementDescriptor().getPartMappingType(); if ( partMappingType instanceof EntityMappingType entityMappingType ) { entityMappingTypeByTableAlias.put( tableAlias, entityMappingType ); } @@ -1845,7 +1844,7 @@ public String getAdjustedSqlString() { @Override public String toString() { - final StringBuilder buffer = + final var buffer = new StringBuilder( "ParameterInterpretationImpl (" ) .append( sqlString ) .append( ") : {" ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/AbstractSqmSelectionQuery.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/AbstractSqmSelectionQuery.java index f4da8f36a638..c096c00d0f67 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/AbstractSqmSelectionQuery.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/AbstractSqmSelectionQuery.java @@ -4,36 +4,27 @@ */ package org.hibernate.query.sqm.internal; -import jakarta.persistence.TemporalType; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.graph.spi.AppliedGraph; import org.hibernate.type.BindableType; -import org.hibernate.query.IllegalSelectQueryException; import org.hibernate.query.KeyedPage; import org.hibernate.query.KeyedResultList; import org.hibernate.query.Page; -import org.hibernate.query.QueryLogging; import org.hibernate.query.SelectionQuery; import org.hibernate.query.hql.internal.QuerySplitter; import org.hibernate.query.spi.AbstractSelectionQuery; import org.hibernate.query.spi.HqlInterpretation; import org.hibernate.query.spi.MutableQueryOptions; -import org.hibernate.query.spi.ParameterMetadataImplementor; -import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryOptions; import org.hibernate.query.spi.QueryParameterBinding; import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.query.spi.SelectQueryPlan; import org.hibernate.query.sqm.spi.NamedSqmQueryMemento; import org.hibernate.query.sqm.tree.SqmStatement; -import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter; import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper; -import org.hibernate.query.sqm.tree.expression.SqmParameter; import org.hibernate.query.sqm.tree.select.SqmSelectStatement; import org.hibernate.query.sqm.tree.select.SqmSelection; import org.hibernate.sql.results.internal.TupleMetadata; -import org.hibernate.type.BasicTypeRegistry; import java.util.List; @@ -42,6 +33,7 @@ import static org.hibernate.cfg.QuerySettings.FAIL_ON_PAGINATION_OVER_COLLECTION_FETCH; import static org.hibernate.query.KeyedPage.KeyInterpretation.KEY_OF_FIRST_ON_NEXT_PAGE; +import static org.hibernate.query.QueryLogging.QUERY_MESSAGE_LOGGER; import static org.hibernate.query.sqm.internal.KeyedResult.collectKeys; import static org.hibernate.query.sqm.internal.KeyedResult.collectResults; import static org.hibernate.query.sqm.internal.SqmUtil.isHqlTuple; @@ -82,12 +74,13 @@ protected boolean needsDistinct(boolean containsCollectionFetches, boolean hasLi } protected static boolean hasAppliedGraph(MutableQueryOptions queryOptions) { - final AppliedGraph appliedGraph = queryOptions.getAppliedGraph(); + final var appliedGraph = queryOptions.getAppliedGraph(); return appliedGraph != null && appliedGraph.getSemantic() != null; } protected void errorOrLogForPaginationWithCollectionFetch() { - if ( getSessionFactory().getSessionFactoryOptions().isFailOnPaginationOverCollectionFetchEnabled() ) { + if ( getSessionFactory().getSessionFactoryOptions() + .isFailOnPaginationOverCollectionFetchEnabled() ) { throw new HibernateException( "setFirstResult() or setMaxResults() specified with collection fetch join " + "(in-memory pagination was about to be applied, but '" @@ -96,7 +89,7 @@ protected void errorOrLogForPaginationWithCollectionFetch() { ); } else { - QueryLogging.QUERY_MESSAGE_LOGGER.firstOrMaxResultsSpecifiedWithCollectionFetch(); + QUERY_MESSAGE_LOGGER.firstOrMaxResultsSpecifiedWithCollectionFetch(); } } @@ -105,51 +98,44 @@ protected void errorOrLogForPaginationWithCollectionFetch() { public abstract DomainParameterXref getDomainParameterXref(); public abstract TupleMetadata getTupleMetadata(); - private SqmSelectStatement getSqmSelectStatement() { - if ( getSqmStatement() instanceof SqmSelectStatement selectStatement ) { - return selectStatement; - } - else { - throw new IllegalSelectQueryException( "Not a select query" ); - } - } - protected void copyParameterBindings(QueryParameterBindings oldParameterBindings) { - final QueryParameterBindings parameterBindings = getQueryParameterBindings(); + final var parameterBindings = getQueryParameterBindings(); oldParameterBindings.visitBindings( (queryParameter, binding) -> { if ( binding.isBound() ) { //noinspection unchecked - final QueryParameterBinding newBinding = (QueryParameterBinding) parameterBindings.getBinding( queryParameter ); + final var newBinding = (QueryParameterBinding) parameterBindings.getBinding( queryParameter ); //noinspection unchecked - final BindableType bindType = (BindableType) binding.getBindType(); - final TemporalType explicitTemporalPrecision = binding.getExplicitTemporalPrecision(); + final var bindType = (BindableType) binding.getBindType(); + final var explicitTemporalPrecision = binding.getExplicitTemporalPrecision(); if ( binding.isMultiValued() ) { + final var bindValues = binding.getBindValues(); if ( explicitTemporalPrecision != null ) { - newBinding.setBindValues( binding.getBindValues(), explicitTemporalPrecision, getSessionFactory().getTypeConfiguration() ); + newBinding.setBindValues( bindValues, explicitTemporalPrecision, getTypeConfiguration() ); } else if ( bindType != null ) { - newBinding.setBindValues( binding.getBindValues(), bindType ); + newBinding.setBindValues( bindValues, bindType ); } else { - newBinding.setBindValues( binding.getBindValues() ); + newBinding.setBindValues( bindValues ); } } else { + final var bindValue = binding.getBindValue(); if ( explicitTemporalPrecision != null ) { - newBinding.setBindValue( binding.getBindValue(), explicitTemporalPrecision ); + newBinding.setBindValue( bindValue, explicitTemporalPrecision ); } else if ( bindType != null ) { - newBinding.setBindValue( binding.getBindValue(), bindType ); + newBinding.setBindValue( bindValue, bindType ); } else { - newBinding.setBindValue( binding.getBindValue() ); + newBinding.setBindValue( bindValue ); } } } } ); // Parameters might be created through HibernateCriteriaBuilder.value which we need to bind here - for ( SqmParameter sqmParameter : getDomainParameterXref().getParameterResolutions().getSqmParameters() ) { + for ( var sqmParameter : getDomainParameterXref().getParameterResolutions().getSqmParameters() ) { if ( sqmParameter instanceof SqmJpaCriteriaParameterWrapper wrapper ) { bindCriteriaParameter( wrapper ); } @@ -157,7 +143,7 @@ else if ( bindType != null ) { } protected void bindCriteriaParameter(SqmJpaCriteriaParameterWrapper sqmParameter) { - final JpaCriteriaParameter criteriaParameter = sqmParameter.getJpaCriteriaParameter(); + final var criteriaParameter = sqmParameter.getJpaCriteriaParameter(); final T value = criteriaParameter.getValue(); // We don't set a null value, unless the type is also null which // is the case when using HibernateCriteriaBuilder.value @@ -181,7 +167,7 @@ public KeyedResultList getKeyedResultList(KeyedPage keyedPage) { if ( keyedPage == null ) { throw new IllegalArgumentException( "KeyedPage was null" ); } - final List> results = + final var results = new SqmSelectionQueryImpl>( this, keyedPage ) .getResultList(); final int pageSize = keyedPage.getPage().getSize(); @@ -227,8 +213,8 @@ private static KeyedPage previousPage(KeyedPage keyedPage, List getExpectedResultType(); protected SelectQueryPlan buildSelectQueryPlan() { - final SqmSelectStatement statement = (SqmSelectStatement) getSqmStatement(); - final SqmSelectStatement[] concreteSqmStatements = QuerySplitter.split( statement ); + final var statement = (SqmSelectStatement) getSqmStatement(); + final var concreteSqmStatements = QuerySplitter.split( statement ); return concreteSqmStatements.length > 1 ? buildAggregatedQueryPlan( concreteSqmStatements ) : buildConcreteQueryPlan( concreteSqmStatements[0] ); @@ -280,9 +266,8 @@ protected void applySqmOptions(NamedSqmQueryMemento memento) { } if ( memento.getParameterTypes() != null ) { - final BasicTypeRegistry basicTypeRegistry = - getSessionFactory().getTypeConfiguration().getBasicTypeRegistry(); - final ParameterMetadataImplementor parameterMetadata = getParameterMetadata(); + final var basicTypeRegistry = getTypeConfiguration().getBasicTypeRegistry(); + final var parameterMetadata = getParameterMetadata(); memento.getParameterTypes().forEach( (key, value) -> parameterMetadata.getQueryParameter( key ) .applyAnticipatedType( basicTypeRegistry.getRegisteredType( value ) ) ); @@ -291,7 +276,7 @@ protected void applySqmOptions(NamedSqmQueryMemento memento) { protected TupleMetadata buildTupleMetadata(SqmStatement statement, Class resultType) { if ( statement instanceof SqmSelectStatement select ) { - final List> selections = + final var selections = select.getQueryPart().getFirstQuerySpec().getSelectClause().getSelections(); return isTupleMetadataRequired( resultType, selections.get(0) ) ? getTupleMetadata( selections ) @@ -380,7 +365,7 @@ protected static HqlInterpretation interpretation( NamedSqmQueryMemento memento, Class expectedResultType, SharedSessionContractImplementor session) { - final QueryEngine queryEngine = session.getFactory().getQueryEngine(); + final var queryEngine = session.getFactory().getQueryEngine(); return queryEngine.getInterpretationCache() .resolveHqlInterpretation( memento.getHqlString(), expectedResultType, queryEngine.getHqlTranslator() ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmQueryImpl.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmQueryImpl.java index 1cbe89f1fae8..659625ca36ff 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmQueryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmQueryImpl.java @@ -25,17 +25,13 @@ import org.hibernate.ScrollMode; import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.generator.Generator; import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.RootGraph; -import org.hibernate.graph.spi.AppliedGraph; import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.id.BulkInsertionCapableIdentifierGenerator; import org.hibernate.id.OptimizableGenerator; -import org.hibernate.id.enhanced.Optimizer; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping; -import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.query.IllegalQueryOperationException; import org.hibernate.query.Page; @@ -53,33 +49,25 @@ import org.hibernate.query.spi.DelegatingQueryOptions; import org.hibernate.query.spi.DomainQueryExecutionContext; import org.hibernate.query.spi.HqlInterpretation; -import org.hibernate.query.spi.MutableQueryOptions; import org.hibernate.query.spi.NonSelectQueryPlan; import org.hibernate.query.spi.ParameterMetadataImplementor; -import org.hibernate.query.spi.QueryInterpretationCache; import org.hibernate.query.spi.QueryOptions; import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.query.spi.ScrollableResultsImplementor; import org.hibernate.query.spi.SelectQueryPlan; -import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; import org.hibernate.query.sqm.spi.InterpretationsKeySource; import org.hibernate.query.sqm.spi.NamedSqmQueryMemento; import org.hibernate.query.sqm.tree.AbstractSqmDmlStatement; -import org.hibernate.query.sqm.tree.SqmCopyContext; import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement; -import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper; -import org.hibernate.query.sqm.tree.expression.SqmParameter; import org.hibernate.query.sqm.tree.from.SqmRoot; import org.hibernate.query.sqm.tree.insert.SqmInsertStatement; import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement; -import org.hibernate.query.sqm.tree.insert.SqmValues; -import org.hibernate.query.sqm.tree.select.SqmQueryPart; import org.hibernate.query.sqm.tree.select.SqmSelectStatement; import org.hibernate.query.sqm.tree.update.SqmUpdateStatement; import org.hibernate.sql.results.internal.TupleMetadata; -import org.hibernate.sql.results.spi.ListResultsConsumer; +import org.hibernate.sql.results.spi.ListResultsConsumer.UniqueSemantic; import org.hibernate.sql.results.spi.SingleResultConsumer; import java.time.Instant; @@ -111,6 +99,8 @@ import static org.hibernate.query.sqm.internal.SqmUtil.isSelect; import static org.hibernate.query.sqm.internal.SqmUtil.validateCriteriaQuery; import static org.hibernate.query.sqm.internal.SqmUtil.verifyIsNonSelectStatement; +import static org.hibernate.query.sqm.internal.SqmUtil.verifyIsSelectStatement; +import static org.hibernate.query.sqm.tree.SqmCopyContext.simpleContext; /** * {@link Query} implementation based on an SQM @@ -212,7 +202,7 @@ public SqmQueryImpl( SharedSessionContractImplementor session) { super( session ); hql = CRITERIA_HQL_STRING; - sqm = copyAst ? criteria.copy( SqmCopyContext.simpleContext() ) : criteria; + sqm = copyAst ? criteria.copy( simpleContext() ) : criteria; queryStringCacheKey = sqm; // Cache immutable query plans by default setQueryPlanCacheable( !copyAst || session.isCriteriaPlanCacheEnabled() ); @@ -220,13 +210,14 @@ public SqmQueryImpl( setComment( hql ); domainParameterXref = DomainParameterXref.from( sqm ); - parameterMetadata = !domainParameterXref.hasParameters() - ? ParameterMetadataImpl.EMPTY - : new ParameterMetadataImpl( domainParameterXref.getQueryParameters() ); + parameterMetadata = + domainParameterXref.hasParameters() + ? new ParameterMetadataImpl( domainParameterXref.getQueryParameters() ) + : ParameterMetadataImpl.EMPTY; parameterBindings = parameterMetadata.createBindings( session.getFactory() ); // Parameters might be created through HibernateCriteriaBuilder.value which we need to bind here - for ( SqmParameter sqmParameter : domainParameterXref.getParameterResolutions().getSqmParameters() ) { + for ( var sqmParameter : domainParameterXref.getParameterResolutions().getSqmParameters() ) { if ( sqmParameter instanceof SqmJpaCriteriaParameterWrapper wrapper ) { bindCriteriaParameter( wrapper ); } @@ -240,7 +231,7 @@ public SqmQueryImpl( private static void validateQuery(Class expectedResultType, SqmStatement sqm, String hql) { if ( sqm instanceof SqmSelectStatement selectStatement ) { - final SqmQueryPart queryPart = selectStatement.getQueryPart(); + final var queryPart = selectStatement.getQueryPart(); // For criteria queries, we have to validate the fetch structure here queryPart.validateQueryStructureAndFetchOwners(); validateCriteriaQuery( queryPart ); @@ -279,11 +270,12 @@ protected void setSqmStatement(SqmSelectStatement sqm) { this.sqm = sqm; this.queryStringCacheKey = sqm; - final QueryParameterBindings oldParameterBindings = parameterBindings; + final var oldParameterBindings = parameterBindings; domainParameterXref = DomainParameterXref.from( sqm ); - parameterMetadata = !domainParameterXref.hasParameters() - ? ParameterMetadataImpl.EMPTY - : new ParameterMetadataImpl( domainParameterXref.getQueryParameters() ); + parameterMetadata = + domainParameterXref.hasParameters() + ? new ParameterMetadataImpl( domainParameterXref.getQueryParameters() ) + : ParameterMetadataImpl.EMPTY; parameterBindings = parameterMetadata.createBindings( getSessionFactory() ); copyParameterBindings( oldParameterBindings ); } @@ -351,7 +343,7 @@ protected void prepareForExecution() { protected void verifySelect() { try { - SqmUtil.verifyIsSelectStatement( getSqmStatement(), hql ); + verifyIsSelectStatement( getSqmStatement(), hql ); } catch (IllegalQueryOperationException e) { // per JPA @@ -363,27 +355,28 @@ protected void verifySelect() { @Override public long getResultCount() { verifySelect(); - final DelegatingDomainQueryExecutionContext context = new DelegatingDomainQueryExecutionContext(this) { + final var context = new DelegatingDomainQueryExecutionContext(this) { @Override public QueryOptions getQueryOptions() { return QueryOptions.NONE; } }; - final SqmSelectStatement sqmStatement = (SqmSelectStatement) getSqmStatement(); + final var sqmStatement = (SqmSelectStatement) getSqmStatement(); return buildConcreteQueryPlan( sqmStatement.createCountQuery(), Long.class, null, getQueryOptions() ) .executeQuery( context, SingleResultConsumer.instance() ); } protected List doList() { verifySelect(); - final SqmSelectStatement statement = (SqmSelectStatement) getSqmStatement(); + final var statement = (SqmSelectStatement) getSqmStatement(); final boolean containsCollectionFetches = statement.containsCollectionFetches() || containsCollectionFetches( getQueryOptions() ); final boolean hasLimit = hasLimit( statement, getQueryOptions() ); final boolean needsDistinct = needsDistinct( containsCollectionFetches, hasLimit, statement ); - final List list = resolveSelectQueryPlan() - .performList( executionContextForDoList( containsCollectionFetches, hasLimit, needsDistinct ) ); + final var list = + resolveSelectQueryPlan() + .performList( executionContextForDoList( containsCollectionFetches, hasLimit, needsDistinct ) ); return needsDistinct ? handleDistinct( hasLimit, statement, list ) : list; } @@ -408,24 +401,19 @@ private List handleDistinct(boolean hasLimit, SqmSelectStatement statement // TODO: very similar to SqmSelectionQueryImpl.executionContext() protected DomainQueryExecutionContext executionContextForDoList( boolean containsCollectionFetches, boolean hasLimit, boolean needsDistinct) { - final MutableQueryOptions originalQueryOptions; + final var originalQueryOptions = getQueryOptions(); final QueryOptions normalizedQueryOptions; if ( hasLimit && containsCollectionFetches ) { errorOrLogForPaginationWithCollectionFetch(); - - originalQueryOptions = getQueryOptions(); normalizedQueryOptions = needsDistinct ? omitSqlQueryOptionsWithUniqueSemanticFilter( originalQueryOptions, true, false ) : omitSqlQueryOptions( originalQueryOptions, true, false ); } + else if ( needsDistinct ) { + normalizedQueryOptions = uniqueSemanticQueryOptions( originalQueryOptions ); + } else { - if ( needsDistinct ) { - originalQueryOptions = getQueryOptions(); - normalizedQueryOptions = uniqueSemanticQueryOptions( originalQueryOptions ); - } - else { - return this; - } + return this; } if ( originalQueryOptions == normalizedQueryOptions ) { @@ -441,20 +429,15 @@ public QueryOptions getQueryOptions() { } } - public static QueryOptions uniqueSemanticQueryOptions(QueryOptions originalOptions) { - return originalOptions.getUniqueSemantic() == ListResultsConsumer.UniqueSemantic.FILTER + public static QueryOptions uniqueSemanticQueryOptions(final QueryOptions originalOptions) { + return originalOptions.getUniqueSemantic() == UniqueSemantic.FILTER ? originalOptions - : new UniqueSemanticFilterQueryOption( originalOptions ); - } - - private static class UniqueSemanticFilterQueryOption extends DelegatingQueryOptions{ - private UniqueSemanticFilterQueryOption(QueryOptions queryOptions) { - super( queryOptions ); - } - @Override - public ListResultsConsumer.UniqueSemantic getUniqueSemantic() { - return ListResultsConsumer.UniqueSemantic.FILTER; - } + : new DelegatingQueryOptions( originalOptions ) { + @Override + public UniqueSemantic getUniqueSemantic() { + return UniqueSemantic.FILTER; + } + }; } @Override @@ -474,23 +457,20 @@ public boolean isQueryPlanCacheable() { : super.isQueryPlanCacheable(); } + // TODO: very similar, but not identical to SqmSelectionQueryImpl.resolveQueryPlan() private SelectQueryPlan resolveSelectQueryPlan() { - final QueryInterpretationCache queryCache = interpretationCache(); + final var queryCache = getInterpretationCache(); if ( queryCache.isEnabled() ) { - final QueryInterpretationCache.Key cacheKey = createInterpretationsKey( this ); - return cacheKey != null - ? queryCache.resolveSelectQueryPlan( cacheKey, this::buildSelectQueryPlan ) - : buildSelectQueryPlan(); + final var cacheKey = createInterpretationsKey( this ); + return cacheKey == null + ? buildSelectQueryPlan() + : queryCache.resolveSelectQueryPlan( cacheKey, this::buildSelectQueryPlan ); } else { return buildSelectQueryPlan(); } } - private QueryInterpretationCache interpretationCache() { - return getSessionFactory().getQueryEngine().getInterpretationCache(); - } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Update / delete / insert query execution @@ -543,8 +523,8 @@ private NonSelectQueryPlan resolveNonSelectQueryPlan() { NonSelectQueryPlan queryPlan = null; - final QueryInterpretationCache.Key cacheKey = generateNonSelectKey( this ); - final QueryInterpretationCache interpretationCache = interpretationCache(); + final var cacheKey = generateNonSelectKey( this ); + final var interpretationCache = getInterpretationCache(); if ( cacheKey != null ) { queryPlan = interpretationCache.getNonSelectQueryPlan( cacheKey ); } @@ -578,65 +558,47 @@ else if ( sqmStatement instanceof SqmInsertStatement ) { } private NonSelectQueryPlan buildDeleteQueryPlan() { - final SqmDeleteStatement[] concreteSqmStatements = + final var concreteSqmStatements = QuerySplitter.split( (SqmDeleteStatement) getSqmStatement() ); return concreteSqmStatements.length > 1 ? buildAggregatedDeleteQueryPlan( concreteSqmStatements ) : buildConcreteDeleteQueryPlan( concreteSqmStatements[0] ); } - private NonSelectQueryPlan buildConcreteDeleteQueryPlan(SqmDeleteStatement sqmDelete) { - final EntityDomainType entityDomainType = sqmDelete.getTarget().getModel(); - final EntityPersister persister = - getSessionFactory().getMappingMetamodel() - .getEntityDescriptor( entityDomainType.getHibernateEntityName() ); - final SqmMultiTableMutationStrategy multiTableStrategy = persister.getSqmMultiTableMutationStrategy(); - if ( multiTableStrategy != null ) { - // NOTE : MultiTableDeleteQueryPlan and SqmMultiTableMutationStrategy already handle soft-deletes internally - return new MultiTableDeleteQueryPlan( sqmDelete, domainParameterXref, multiTableStrategy ); - } - else { - return new SimpleDeleteQueryPlan( persister, sqmDelete, domainParameterXref ); - } + private NonSelectQueryPlan buildConcreteDeleteQueryPlan(SqmDeleteStatement deleteStatement) { + final var entityDomainType = deleteStatement.getTarget().getModel(); + String entityDomainType1 = entityDomainType.getHibernateEntityName(); + final var persister = getMappingMetamodel().getEntityDescriptor( entityDomainType1 ); + final var multiTableStrategy = persister.getSqmMultiTableMutationStrategy(); + return multiTableStrategy != null + // NOTE : MultiTableDeleteQueryPlan and SqmMultiTableMutationStrategy already handle soft-deletes internally + ? new MultiTableDeleteQueryPlan( deleteStatement, domainParameterXref, multiTableStrategy ) + : new SimpleDeleteQueryPlan( persister, deleteStatement, domainParameterXref ); } - private NonSelectQueryPlan buildAggregatedDeleteQueryPlan(SqmDeleteStatement[] concreteSqmStatements) { - final NonSelectQueryPlan[] aggregatedQueryPlans = new NonSelectQueryPlan[ concreteSqmStatements.length ]; - for ( int i = 0, x = concreteSqmStatements.length; i < x; i++ ) { - aggregatedQueryPlans[i] = buildConcreteDeleteQueryPlan( concreteSqmStatements[i] ); + private NonSelectQueryPlan buildAggregatedDeleteQueryPlan(SqmDeleteStatement[] deleteStatements) { + final var aggregatedQueryPlans = new NonSelectQueryPlan[deleteStatements.length]; + for ( int i = 0, x = deleteStatements.length; i < x; i++ ) { + aggregatedQueryPlans[i] = buildConcreteDeleteQueryPlan( deleteStatements[i] ); } return new AggregatedNonSelectQueryPlanImpl( aggregatedQueryPlans ); } private NonSelectQueryPlan buildUpdateQueryPlan() { - final SqmUpdateStatement sqmUpdate = (SqmUpdateStatement) getSqmStatement(); - final EntityPersister persister = - getSessionFactory().getMappingMetamodel() - .getEntityDescriptor( sqmUpdate.getTarget().getModel().getHibernateEntityName() ); - final SqmMultiTableMutationStrategy multiTableStrategy = persister.getSqmMultiTableMutationStrategy(); + final var sqmUpdate = (SqmUpdateStatement) getSqmStatement(); + String entityDomainType = sqmUpdate.getTarget().getModel().getHibernateEntityName(); + final var persister = getMappingMetamodel().getEntityDescriptor( entityDomainType ); + final var multiTableStrategy = persister.getSqmMultiTableMutationStrategy(); return multiTableStrategy == null ? new SimpleNonSelectQueryPlan( sqmUpdate, domainParameterXref ) : new MultiTableUpdateQueryPlan( sqmUpdate, domainParameterXref, multiTableStrategy ); } private NonSelectQueryPlan buildInsertQueryPlan() { - final SqmInsertStatement sqmInsert = (SqmInsertStatement) getSqmStatement(); - final EntityPersister persister = - getSessionFactory().getMappingMetamodel() - .getEntityDescriptor( sqmInsert.getTarget().getModel().getHibernateEntityName() ); - - boolean useMultiTableInsert = persister.hasMultipleTables(); - if ( !useMultiTableInsert && !isSimpleValuesInsert( sqmInsert, persister ) ) { - final Generator identifierGenerator = persister.getGenerator(); - if ( identifierGenerator instanceof BulkInsertionCapableIdentifierGenerator - && identifierGenerator instanceof OptimizableGenerator optimizableGenerator ) { - final Optimizer optimizer = optimizableGenerator.getOptimizer(); - if ( optimizer != null && optimizer.getIncrementSize() > 1 ) { - useMultiTableInsert = !hasIdentifierAssigned( sqmInsert, persister ); - } - } - } - if ( useMultiTableInsert ) { + final var sqmInsert = (SqmInsertStatement) getSqmStatement(); + String entityDomainType = sqmInsert.getTarget().getModel().getHibernateEntityName(); + final var persister = getMappingMetamodel().getEntityDescriptor( entityDomainType ); + if ( useMultiTableInsert( persister, sqmInsert ) ) { return new MultiTableInsertQueryPlan( sqmInsert, domainParameterXref, @@ -646,29 +608,47 @@ private NonSelectQueryPlan buildInsertQueryPlan() { else if ( sqmInsert instanceof SqmInsertValuesStatement insertValues && insertValues.getValuesList().size() != 1 && !getSessionFactory().getJdbcServices().getDialect().supportsValuesListForInsert() ) { - // Split insert-values queries if the dialect doesn't support values lists - final List valuesList = insertValues.getValuesList(); - final NonSelectQueryPlan[] planParts = new NonSelectQueryPlan[valuesList.size()]; - for ( int i = 0; i < valuesList.size(); i++ ) { - final SqmInsertValuesStatement subInsert = - insertValues.copyWithoutValues( SqmCopyContext.simpleContext() ); - subInsert.values( valuesList.get( i ) ); - planParts[i] = new SimpleNonSelectQueryPlan( subInsert, domainParameterXref ); - } + return buildAggregateInsertQueryPlan( insertValues ); + } + else { + return new SimpleNonSelectQueryPlan( sqmInsert, domainParameterXref ); + } + } - return new AggregatedNonSelectQueryPlanImpl( planParts ); + private NonSelectQueryPlan buildAggregateInsertQueryPlan(SqmInsertValuesStatement insertValues) { + // Split insert-values queries if the dialect doesn't support values lists + final var valuesList = insertValues.getValuesList(); + final var planParts = new NonSelectQueryPlan[valuesList.size()]; + for ( int i = 0; i < valuesList.size(); i++ ) { + final var subInsert = insertValues.copyWithoutValues( simpleContext() ); + subInsert.values( valuesList.get( i ) ); + planParts[i] = new SimpleNonSelectQueryPlan( subInsert, domainParameterXref ); } + return new AggregatedNonSelectQueryPlanImpl( planParts ); + } - return new SimpleNonSelectQueryPlan( sqmInsert, domainParameterXref ); + private boolean useMultiTableInsert(EntityPersister persister, SqmInsertStatement sqmInsert) { + boolean useMultiTableInsert = persister.hasMultipleTables(); + if ( !useMultiTableInsert && !isSimpleValuesInsert( sqmInsert, persister ) ) { + final var identifierGenerator = persister.getGenerator(); + if ( identifierGenerator instanceof BulkInsertionCapableIdentifierGenerator + && identifierGenerator instanceof OptimizableGenerator optimizableGenerator ) { + final var optimizer = optimizableGenerator.getOptimizer(); + if ( optimizer != null && optimizer.getIncrementSize() > 1 ) { + useMultiTableInsert = !hasIdentifierAssigned( sqmInsert, persister ); + } + } + } + return useMultiTableInsert; } protected boolean hasIdentifierAssigned(SqmInsertStatement sqmInsert, EntityPersister entityDescriptor) { - final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping(); + final var identifierMapping = entityDescriptor.getIdentifierMapping(); final String partName = identifierMapping instanceof SingleAttributeIdentifierMapping ? identifierMapping.getAttributeName() : EntityIdentifierMapping.ID_ROLE_NAME; - for ( SqmPath insertionTargetPath : sqmInsert.getInsertionTargetPaths() ) { + for ( var insertionTargetPath : sqmInsert.getInsertionTargetPaths() ) { if ( insertionTargetPath.getLhs() instanceof SqmRoot ) { if ( insertionTargetPath.getReferencedPathSource().getPathName().equals( partName ) ) { return true; @@ -799,25 +779,30 @@ protected void collectHints(Map hints) { putIfNotNull( hints, HINT_FETCH_SIZE, getFetchSize() ); + final var queryOptions = getQueryOptions(); + if ( isCacheable() ) { hints.put( HINT_CACHEABLE, true ); putIfNotNull( hints, HINT_CACHE_REGION, getCacheRegion() ); putIfNotNull( hints, HINT_CACHE_MODE, getCacheMode() ); - putIfNotNull( hints, HINT_SPEC_CACHE_RETRIEVE_MODE, getQueryOptions().getCacheRetrieveMode() ); - putIfNotNull( hints, HINT_SPEC_CACHE_STORE_MODE, getQueryOptions().getCacheStoreMode() ); - putIfNotNull( hints, HINT_JAVAEE_CACHE_RETRIEVE_MODE, getQueryOptions().getCacheRetrieveMode() ); - putIfNotNull( hints, HINT_JAVAEE_CACHE_STORE_MODE, getQueryOptions().getCacheStoreMode() ); + putIfNotNull( hints, HINT_SPEC_CACHE_RETRIEVE_MODE, queryOptions.getCacheRetrieveMode() ); + putIfNotNull( hints, HINT_SPEC_CACHE_STORE_MODE, queryOptions.getCacheStoreMode() ); + putIfNotNull( hints, HINT_JAVAEE_CACHE_RETRIEVE_MODE, queryOptions.getCacheRetrieveMode() ); + putIfNotNull( hints, HINT_JAVAEE_CACHE_STORE_MODE, queryOptions.getCacheStoreMode() ); } - final AppliedGraph appliedGraph = getQueryOptions().getAppliedGraph(); - if ( appliedGraph != null && appliedGraph.getSemantic() != null ) { - hints.put( appliedGraph.getSemantic().getJakartaHintName(), appliedGraph ); - hints.put( appliedGraph.getSemantic().getJpaHintName(), appliedGraph ); + final var appliedGraph = queryOptions.getAppliedGraph(); + if ( appliedGraph != null ) { + final var semantic = appliedGraph.getSemantic(); + if ( semantic != null ) { + hints.put( semantic.getJakartaHintName(), appliedGraph ); + hints.put( semantic.getJpaHintName(), appliedGraph ); + } } - putIfNotNull( hints, HINT_FOLLOW_ON_STRATEGY, getQueryOptions().getLockOptions().getFollowOnStrategy() ); - putIfNotNull( hints, HINT_FOLLOW_ON_LOCKING, getQueryOptions().getLockOptions().getFollowOnLocking() ); + putIfNotNull( hints, HINT_FOLLOW_ON_STRATEGY, queryOptions.getLockOptions().getFollowOnStrategy() ); + putIfNotNull( hints, HINT_FOLLOW_ON_LOCKING, queryOptions.getLockOptions().getFollowOnLocking() ); } @Override @@ -904,7 +889,7 @@ public NamedSqmQueryMemento toMemento(String name) { getResultType(), getSession().isCriteriaCopyTreeEnabled() ? getSqmStatement() // the statement has already been copied - : getSqmStatement().copy( SqmCopyContext.simpleContext() ), + : getSqmStatement().copy( simpleContext() ), getQueryOptions().getLimit().getFirstRow(), getQueryOptions().getLimit().getMaxRows(), isCacheable(), diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmSelectionQueryImpl.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmSelectionQueryImpl.java index 9bd0900b52a5..e53339b892c4 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmSelectionQueryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmSelectionQueryImpl.java @@ -30,11 +30,9 @@ import org.hibernate.ScrollMode; import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.graph.spi.AppliedGraph; import org.hibernate.internal.util.collections.IdentitySet; import org.hibernate.query.KeyedPage; import org.hibernate.query.Order; -import org.hibernate.query.Page; import org.hibernate.query.QueryParameter; import org.hibernate.query.ResultListTransformer; import org.hibernate.query.SelectionQuery; @@ -46,9 +44,7 @@ import org.hibernate.type.BindableType; import org.hibernate.query.spi.DomainQueryExecutionContext; import org.hibernate.query.spi.HqlInterpretation; -import org.hibernate.query.spi.MutableQueryOptions; import org.hibernate.query.spi.ParameterMetadataImplementor; -import org.hibernate.query.spi.QueryInterpretationCache; import org.hibernate.query.spi.QueryOptions; import org.hibernate.query.spi.QueryParameterBinding; import org.hibernate.query.spi.QueryParameterBindings; @@ -58,16 +54,11 @@ import org.hibernate.query.sqm.SqmSelectionQuery; import org.hibernate.query.sqm.spi.InterpretationsKeySource; import org.hibernate.query.sqm.spi.SqmSelectionQueryImplementor; -import org.hibernate.query.sqm.tree.SqmCopyContext; import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper; -import org.hibernate.query.sqm.tree.expression.SqmParameter; -import org.hibernate.query.sqm.tree.select.SqmQueryPart; import org.hibernate.query.sqm.tree.select.SqmSelectStatement; -import org.hibernate.query.sqm.tree.select.SqmSelection; import org.hibernate.sql.results.internal.TupleMetadata; import org.hibernate.sql.results.spi.ResultsConsumer; import org.hibernate.sql.results.spi.SingleResultConsumer; -import org.hibernate.type.descriptor.java.JavaType; import static org.hibernate.jpa.HibernateHints.HINT_CACHEABLE; import static org.hibernate.jpa.HibernateHints.HINT_CACHE_MODE; @@ -85,7 +76,9 @@ import static org.hibernate.query.sqm.internal.KeyBasedPagination.paginate; import static org.hibernate.query.sqm.internal.SqmInterpretationsKey.createInterpretationsKey; import static org.hibernate.query.sqm.internal.SqmUtil.isSelectionAssignableToResultType; +import static org.hibernate.query.sqm.internal.SqmUtil.verifyIsSelectStatement; import static org.hibernate.query.sqm.tree.SqmCopyContext.noParamCopyContext; +import static org.hibernate.query.sqm.tree.SqmCopyContext.simpleContext; /** * @author Steve Ebersole @@ -116,7 +109,7 @@ public SqmSelectionQueryImpl( this.hql = hql; this.queryStringCacheKey = hql; - SqmUtil.verifyIsSelectStatement( hqlInterpretation.getSqmStatement(), hql ); + verifyIsSelectStatement( hqlInterpretation.getSqmStatement(), hql ); this.sqm = (SqmSelectStatement) hqlInterpretation.getSqmStatement(); this.parameterMetadata = hqlInterpretation.getParameterMetadata(); @@ -181,20 +174,21 @@ public SqmSelectionQueryImpl( super( session ); this.expectedResultType = expectedResultType; hql = CRITERIA_HQL_STRING; - sqm = copyAst ? criteria.copy( SqmCopyContext.simpleContext() ) : criteria; + sqm = copyAst ? criteria.copy( simpleContext() ) : criteria; queryStringCacheKey = sqm; // Cache immutable query plans by default setQueryPlanCacheable( !copyAst || session.isCriteriaPlanCacheEnabled() ); domainParameterXref = DomainParameterXref.from( sqm ); - parameterMetadata = domainParameterXref.hasParameters() - ? new ParameterMetadataImpl( domainParameterXref.getQueryParameters() ) - : ParameterMetadataImpl.EMPTY; + parameterMetadata = + domainParameterXref.hasParameters() + ? new ParameterMetadataImpl( domainParameterXref.getQueryParameters() ) + : ParameterMetadataImpl.EMPTY; parameterBindings = parameterMetadata.createBindings( session.getFactory() ); // Parameters might be created through HibernateCriteriaBuilder.value which we need to bind here - for ( SqmParameter sqmParameter : domainParameterXref.getParameterResolutions().getSqmParameters() ) { + for ( var sqmParameter : domainParameterXref.getParameterResolutions().getSqmParameters() ) { if ( sqmParameter instanceof SqmJpaCriteriaParameterWrapper wrapper ) { bindCriteriaParameter( wrapper ); } @@ -202,7 +196,7 @@ public SqmSelectionQueryImpl( resultType = determineResultType( sqm, expectedResultType ); - final SqmQueryPart queryPart = sqm.getQueryPart(); + final var queryPart = sqm.getQueryPart(); // For criteria queries, we have to validate the fetch structure here queryPart.validateQueryStructureAndFetchOwners(); SqmUtil.validateCriteriaQuery( queryPart ); @@ -217,10 +211,10 @@ public SqmSelectionQueryImpl( SqmSelectionQueryImpl(AbstractSqmSelectionQuery original, KeyedPage keyedPage) { super( original ); - final Page page = keyedPage.getPage(); - final List> key = keyedPage.getKey(); - final List> keyDefinition = keyedPage.getKeyDefinition(); - final List> appliedKeyDefinition = + final var page = keyedPage.getPage(); + final var key = keyedPage.getKey(); + final var keyDefinition = keyedPage.getKeyDefinition(); + final var appliedKeyDefinition = keyedPage.getKeyInterpretation() == KEY_OF_FIRST_ON_NEXT_PAGE ? Order.reverse( keyDefinition ) : keyDefinition; @@ -245,16 +239,17 @@ SqmSelectionQueryImpl(AbstractSqmSelectionQuery original, KeyedPage ke hql = CRITERIA_HQL_STRING; domainParameterXref = DomainParameterXref.from( sqm ); - parameterMetadata = domainParameterXref.hasParameters() - ? new ParameterMetadataImpl( domainParameterXref.getQueryParameters() ) - : ParameterMetadataImpl.EMPTY; + parameterMetadata = + domainParameterXref.hasParameters() + ? new ParameterMetadataImpl( domainParameterXref.getQueryParameters() ) + : ParameterMetadataImpl.EMPTY; // Just use the original parameter bindings since this object is never going to be mutated parameterBindings = parameterMetadata.createBindings( original.getSession().getSessionFactory() ); original.getQueryParameterBindings().visitBindings( this::setBindValues ); // Parameters might be created through HibernateCriteriaBuilder.value which we need to bind here - for ( SqmParameter sqmParameter : domainParameterXref.getParameterResolutions().getSqmParameters() ) { + for ( var sqmParameter : domainParameterXref.getParameterResolutions().getSqmParameters() ) { if ( sqmParameter instanceof SqmJpaCriteriaParameterWrapper parameterWrapper ) { bindCriteriaParameter( parameterWrapper ); } @@ -272,13 +267,12 @@ SqmSelectionQueryImpl(AbstractSqmSelectionQuery original, KeyedPage ke } private void setBindValues(QueryParameter parameter, QueryParameterBinding binding) { - final QueryParameterBinding parameterBinding = parameterBindings.getBinding( binding.getQueryParameter() ); - @SuppressWarnings("deprecation") - final TemporalType explicitTemporalPrecision = binding.getExplicitTemporalPrecision(); + final var parameterBinding = parameterBindings.getBinding( binding.getQueryParameter() ); + final var explicitTemporalPrecision = binding.getExplicitTemporalPrecision(); if ( explicitTemporalPrecision != null ) { if ( binding.isMultiValued() ) { parameterBinding.setBindValues( binding.getBindValues(), explicitTemporalPrecision, - getSessionFactory().getTypeConfiguration() ); + getTypeConfiguration() ); } else { parameterBinding.setBindValue( binding.getBindValue(), explicitTemporalPrecision ); @@ -286,7 +280,7 @@ private void setBindValues(QueryParameter parameter, QueryParameterBindin } else { //noinspection unchecked - final BindableType bindType = (BindableType) binding.getBindType(); + final var bindType = (BindableType) binding.getBindType(); if ( binding.isMultiValued() ) { parameterBinding.setBindValues( binding.getBindValues(), bindType ); } @@ -299,16 +293,16 @@ private void setBindValues(QueryParameter parameter, QueryParameterBindin private static Class determineResultType(SqmSelectStatement sqm, Class expectedResultType) { - final List> selections = sqm.getQuerySpec().getSelectClause().getSelections(); + final var selections = sqm.getQuerySpec().getSelectClause().getSelections(); if ( selections.size() == 1 ) { if ( Object[].class.equals( expectedResultType ) ) { // for JPA compatibility return Object[].class; } else { - final SqmSelection selection = selections.get( 0 ); + final var selection = selections.get( 0 ); if ( isSelectionAssignableToResultType( selection, expectedResultType ) ) { - final JavaType nodeJavaType = selection.getNodeJavaType(); + final var nodeJavaType = selection.getNodeJavaType(); if ( nodeJavaType != null ) { return nodeJavaType.getJavaTypeClass(); } @@ -346,9 +340,10 @@ protected void setSqmStatement(SqmSelectStatement sqm) { final QueryParameterBindings oldParameterBindings = parameterBindings; domainParameterXref = DomainParameterXref.from( sqm ); - parameterMetadata = !domainParameterXref.hasParameters() - ? ParameterMetadataImpl.EMPTY - : new ParameterMetadataImpl( domainParameterXref.getQueryParameters() ); + parameterMetadata = + domainParameterXref.hasParameters() + ? new ParameterMetadataImpl( domainParameterXref.getQueryParameters() ) + : ParameterMetadataImpl.EMPTY; parameterBindings = parameterMetadata.createBindings( getSessionFactory() ); copyParameterBindings( oldParameterBindings ); } @@ -402,7 +397,7 @@ protected void prepareForExecution() { @Override public long getResultCount() { - final DelegatingDomainQueryExecutionContext context = new DelegatingDomainQueryExecutionContext(this) { + final var context = new DelegatingDomainQueryExecutionContext(this) { @Override public QueryOptions getQueryOptions() { return QueryOptions.NONE; @@ -413,14 +408,15 @@ public QueryOptions getQueryOptions() { } protected List doList() { - final SqmSelectStatement statement = getSqmStatement(); + final var statement = getSqmStatement(); final boolean containsCollectionFetches = //TODO: why is this different from QuerySqmImpl.doList()? statement.containsCollectionFetches(); final boolean hasLimit = hasLimit( statement, getQueryOptions() ); final boolean needsDistinct = needsDistinct( containsCollectionFetches, hasLimit, statement ); - final List list = resolveQueryPlan() - .performList( executionContext( hasLimit, containsCollectionFetches ) ); + final var list = + resolveQueryPlan() + .performList( executionContext( hasLimit, containsCollectionFetches ) ); return needsDistinct ? handleDistinct( hasLimit, statement, list ) : list; } @@ -450,8 +446,8 @@ private List handleDistinct(boolean hasLimit, SqmSelectStatement statement private DomainQueryExecutionContext executionContext(boolean hasLimit, boolean containsCollectionFetches) { if ( hasLimit && containsCollectionFetches ) { errorOrLogForPaginationWithCollectionFetch(); - final MutableQueryOptions originalQueryOptions = getQueryOptions(); - final QueryOptions normalizedQueryOptions = omitSqlQueryOptions( originalQueryOptions, true, false ); + final var originalQueryOptions = getQueryOptions(); + final var normalizedQueryOptions = omitSqlQueryOptions( originalQueryOptions, true, false ); if ( originalQueryOptions == normalizedQueryOptions ) { return this; } @@ -487,15 +483,13 @@ public Class getExpectedResultType() { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Query plan + // TODO: very similar, but not identical to SqmQueryImpl.resolveQueryPlan() private SelectQueryPlan resolveQueryPlan() { - final QueryInterpretationCache.Key cacheKey = createInterpretationsKey( this ); - if ( cacheKey != null ) { - return getSessionFactory().getQueryEngine().getInterpretationCache() - .resolveSelectQueryPlan( cacheKey, this::buildSelectQueryPlan ); - } - else { - return buildSelectQueryPlan(); - } + final var cacheKey = createInterpretationsKey( this ); + return cacheKey == null + ? buildSelectQueryPlan() + : getInterpretationCache() + .resolveSelectQueryPlan( cacheKey, this::buildSelectQueryPlan ); } @@ -647,25 +641,30 @@ protected void collectHints(Map hints) { putIfNotNull( hints, HINT_FETCH_SIZE, getFetchSize() ); + final var queryOptions = getQueryOptions(); + if ( isCacheable() ) { hints.put( HINT_CACHEABLE, true ); putIfNotNull( hints, HINT_CACHE_REGION, getCacheRegion() ); putIfNotNull( hints, HINT_CACHE_MODE, getCacheMode() ); - putIfNotNull( hints, HINT_SPEC_CACHE_RETRIEVE_MODE, getQueryOptions().getCacheRetrieveMode() ); - putIfNotNull( hints, HINT_SPEC_CACHE_STORE_MODE, getQueryOptions().getCacheStoreMode() ); - putIfNotNull( hints, HINT_JAVAEE_CACHE_RETRIEVE_MODE, getQueryOptions().getCacheRetrieveMode() ); - putIfNotNull( hints, HINT_JAVAEE_CACHE_STORE_MODE, getQueryOptions().getCacheStoreMode() ); + putIfNotNull( hints, HINT_SPEC_CACHE_RETRIEVE_MODE, queryOptions.getCacheRetrieveMode() ); + putIfNotNull( hints, HINT_SPEC_CACHE_STORE_MODE, queryOptions.getCacheStoreMode() ); + putIfNotNull( hints, HINT_JAVAEE_CACHE_RETRIEVE_MODE, queryOptions.getCacheRetrieveMode() ); + putIfNotNull( hints, HINT_JAVAEE_CACHE_STORE_MODE, queryOptions.getCacheStoreMode() ); } - final AppliedGraph appliedGraph = getQueryOptions().getAppliedGraph(); - if ( appliedGraph != null && appliedGraph.getSemantic() != null ) { - hints.put( appliedGraph.getSemantic().getJakartaHintName(), appliedGraph ); - hints.put( appliedGraph.getSemantic().getJpaHintName(), appliedGraph ); + final var appliedGraph = queryOptions.getAppliedGraph(); + if ( appliedGraph != null ) { + final var semantic = appliedGraph.getSemantic(); + if ( semantic != null ) { + hints.put( semantic.getJakartaHintName(), appliedGraph ); + hints.put( semantic.getJpaHintName(), appliedGraph ); + } } - putIfNotNull( hints, HINT_FOLLOW_ON_STRATEGY, getQueryOptions().getLockOptions().getFollowOnStrategy() ); - putIfNotNull( hints, HINT_FOLLOW_ON_LOCKING, getQueryOptions().getLockOptions().getFollowOnLocking() ); + putIfNotNull( hints, HINT_FOLLOW_ON_STRATEGY, queryOptions.getLockOptions().getFollowOnStrategy() ); + putIfNotNull( hints, HINT_FOLLOW_ON_LOCKING, queryOptions.getLockOptions().getFollowOnLocking() ); } From 2aaeb323ffcb56ae77f7ba2c3a6b151584e15ffb Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 5 Sep 2025 10:26:53 +0200 Subject: [PATCH 4/4] cleanups in SqmUtil --- .../hibernate/query/sqm/internal/SqmUtil.java | 206 +++++++++--------- 1 file changed, 99 insertions(+), 107 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java index 47b185c9f5b6..77a923be89a3 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java @@ -6,11 +6,9 @@ import java.sql.Types; import java.util.ArrayList; -import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.IdentityHashMap; -import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; @@ -22,7 +20,6 @@ import org.hibernate.AssertionFailure; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.internal.util.collections.Stack; import org.hibernate.jpa.spi.JpaCompliance; import org.hibernate.metamodel.mapping.BasicValuedMapping; import org.hibernate.metamodel.mapping.Bindable; @@ -32,8 +29,6 @@ import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.JdbcMapping; -import org.hibernate.metamodel.mapping.MappingModelExpressible; -import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPartContainer; import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.ValuedModelPart; @@ -41,23 +36,17 @@ import org.hibernate.metamodel.model.domain.BasicDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.IdentifiableDomainType; -import org.hibernate.metamodel.model.domain.ManagedDomainType; -import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; import org.hibernate.metamodel.model.domain.internal.EntitySqmPathSource; -import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.query.IllegalMutationQueryException; import org.hibernate.query.IllegalQueryOperationException; import org.hibernate.query.IllegalSelectQueryException; import org.hibernate.query.Order; import org.hibernate.query.QueryTypeMismatchException; import org.hibernate.query.criteria.JpaRoot; -import org.hibernate.query.criteria.JpaSelection; import org.hibernate.query.restriction.Restriction; import org.hibernate.query.spi.QueryParameterBinding; import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.query.spi.QueryParameterImplementor; -import org.hibernate.query.sqm.NodeBuilder; -import org.hibernate.query.sqm.SqmBindableType; import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmQuerySource; @@ -80,10 +69,7 @@ import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; import org.hibernate.query.sqm.tree.from.SqmFrom; import org.hibernate.query.sqm.tree.from.SqmJoin; -import org.hibernate.query.sqm.tree.from.SqmRoot; import org.hibernate.query.sqm.tree.predicate.SqmPredicate; -import org.hibernate.query.sqm.tree.predicate.SqmWhereClause; -import org.hibernate.query.sqm.tree.select.SqmOrderByClause; import org.hibernate.query.sqm.tree.select.SqmQueryGroup; import org.hibernate.query.sqm.tree.select.SqmQueryPart; import org.hibernate.query.sqm.tree.select.SqmQuerySpec; @@ -211,7 +197,7 @@ public static ModelPartContainer getTargetMappingIfNeeded( if ( sqlAstCreationState.getCurrentClauseStack().getCurrent() != Clause.FROM && modelPartContainer.getPartMappingType() != modelPartContainer && sqmPath.getLhs() instanceof SqmFrom ) { - final ModelPart modelPart = + final var modelPart = modelPartContainer instanceof PluralAttributeMapping plural ? getCollectionPart( plural, castNonNull( sqmPath.getNavigablePath().getParent() ) ) : modelPartContainer; @@ -233,7 +219,7 @@ private static boolean shouldRenderTargetSide( else { // If the path is one of the association's target key properties, // we need to render the target side if in group/order by - final Clause clause = sqlAstCreationState.getCurrentClauseStack().getCurrent(); + final var clause = sqlAstCreationState.getCurrentClauseStack().getCurrent(); return clause == Clause.GROUP || clause == Clause.ORDER || !isFkOptimizationAllowed( sqmPath.getLhs(), association ) || inGroupByOrOrderBy( sqmPath, sqlAstCreationState ); @@ -241,19 +227,19 @@ private static boolean shouldRenderTargetSide( } private static boolean inGroupByOrOrderBy(SqmPath sqmPath, SqmToSqlAstConverter converter) { - final Stack queryPartStack = converter.getSqmQueryPartStack(); - final NavigablePath np = sqmPath.getNavigablePath(); + final var queryPartStack = converter.getSqmQueryPartStack(); + final var navigablePath = sqmPath.getNavigablePath(); final Boolean found = queryPartStack.findCurrentFirst( queryPart -> { - final SqmQuerySpec spec = queryPart.getFirstQuerySpec(); - return spec.groupByClauseContains( np, converter ) - || spec.orderByClauseContains( np, converter ) + final var querySpec = queryPart.getFirstQuerySpec(); + return querySpec.groupByClauseContains( navigablePath, converter ) + || querySpec.orderByClauseContains( navigablePath, converter ) ? true : null; } ); return Boolean.TRUE.equals( found ); } private static CollectionPart getCollectionPart(PluralAttributeMapping attribute, NavigablePath path) { - final CollectionPart.Nature nature = CollectionPart.Nature.fromNameExact( path.getLocalName() ); + final var nature = CollectionPart.Nature.fromNameExact( path.getLocalName() ); return nature == null ? null : switch ( nature ) { case ELEMENT -> attribute.getElementDescriptor(); case INDEX -> attribute.getIndexDescriptor(); @@ -274,7 +260,7 @@ public static boolean isFkOptimizationAllowed(SqmPath sqmPath) { if ( sqmPath instanceof SqmJoin sqmJoin ) { switch ( sqmJoin.getSqmJoinType() ) { case LEFT: - final EntityAssociationMapping associationMapping = resolveAssociationMapping( sqmJoin ); + final var associationMapping = resolveAssociationMapping( sqmJoin ); if ( associationMapping != null && isFiltered( associationMapping ) ) { return false; } @@ -300,8 +286,8 @@ public static boolean isFkOptimizationAllowed(SqmPath sqmPath, EntityAssociat // so referring the columns of these rows by default when requesting FK column attributes is sensible. // Users that need to refer to the actual target table columns will have to add an explicit entity join. if ( associationMapping.isFkOptimizationAllowed() - && sqmPath instanceof SqmJoin sqmJoin - && hasJoinTable( associationMapping ) ) { + && sqmPath instanceof SqmJoin sqmJoin + && hasJoinTable( associationMapping ) ) { switch ( sqmJoin.getSqmJoinType() ) { case LEFT: if ( isFiltered( associationMapping ) ) { @@ -328,7 +314,7 @@ else if ( associationMapping instanceof ToOneAttributeMapping toOneAttributeMapp } private static boolean isFiltered(EntityAssociationMapping associationMapping) { - final EntityMappingType entityMappingType = associationMapping.getAssociatedEntityMappingType(); + final var entityMappingType = associationMapping.getAssociatedEntityMappingType(); return !associationMapping.isFkOptimizationAllowed() // When the identifier mappings are different we have a joined subclass entity // which will filter rows based on a discriminator predicate @@ -343,11 +329,11 @@ private static boolean isFiltered(EntityAssociationMapping associationMapping) { } private static @Nullable EntityAssociationMapping resolveAssociationMapping(SqmSingularJoin sqmJoin) { - final MappingMetamodelImplementor metamodel = sqmJoin.nodeBuilder().getMappingMetamodel(); - SingularPersistentAttribute attribute = sqmJoin.getAttribute(); - ManagedDomainType declaringType = attribute.getDeclaringType(); + final var metamodel = sqmJoin.nodeBuilder().getMappingMetamodel(); + var attribute = sqmJoin.getAttribute(); + var declaringType = attribute.getDeclaringType(); if ( declaringType.getPersistenceType() != Type.PersistenceType.ENTITY ) { - final StringBuilder pathBuilder = new StringBuilder(); + final var pathBuilder = new StringBuilder(); do { if ( !pathBuilder.isEmpty() ) { pathBuilder.insert(0, '.'); @@ -376,7 +362,7 @@ private static boolean isFiltered(EntityAssociationMapping associationMapping) { } public static List getWhereClauseNavigablePaths(SqmQuerySpec querySpec) { - final SqmWhereClause where = querySpec.getWhereClause(); + final var where = querySpec.getWhereClause(); return where == null || where.getPredicate() == null ? emptyList() : collectNavigablePaths( List.of( where.getPredicate() ) ); @@ -384,13 +370,13 @@ public static List getWhereClauseNavigablePaths(SqmQuerySpec q } public static List getGroupByNavigablePaths(SqmQuerySpec querySpec) { - final List> expressions = querySpec.getGroupByClauseExpressions(); + final var expressions = querySpec.getGroupByClauseExpressions(); return expressions.isEmpty() ? emptyList() : collectNavigablePaths( expressions ); } public static List getOrderByNavigablePaths(SqmQuerySpec querySpec) { - final SqmOrderByClause order = querySpec.getOrderByClause(); + final var order = querySpec.getOrderByClause(); if ( order == null || order.getSortSpecifications().isEmpty() ) { return emptyList(); } @@ -405,10 +391,10 @@ public static List getOrderByNavigablePaths(SqmQuerySpec query private static List collectNavigablePaths(final List> expressions) { final List navigablePaths = arrayList( expressions.size() ); - final SqmPathVisitor pathVisitor = new SqmPathVisitor( path -> navigablePaths.add( path.getNavigablePath() ) ); - for ( final SqmExpression expression : expressions ) { + final var pathVisitor = new SqmPathVisitor( path -> navigablePaths.add( path.getNavigablePath() ) ); + for ( final var expression : expressions ) { if ( expression instanceof SqmAliasedNodeRef sqmAliasedNodeRef ) { - final NavigablePath navigablePath = sqmAliasedNodeRef.getNavigablePath(); + final var navigablePath = sqmAliasedNodeRef.getNavigablePath(); if ( navigablePath != null ) { navigablePaths.add( navigablePath ); } @@ -424,11 +410,11 @@ public static SqmAttributeJoin findCompatibleFetchJoin( SqmFrom sqmFrom, SqmPathSource pathSource, SqmJoinType requestedJoinType) { - for ( final SqmJoin join : sqmFrom.getSqmJoins() ) { + for ( final var join : sqmFrom.getSqmJoins() ) { if ( join.getModel() == pathSource ) { - final SqmAttributeJoin attributeJoin = (SqmAttributeJoin) join; + final var attributeJoin = (SqmAttributeJoin) join; if ( attributeJoin.isFetched() ) { - final SqmJoinType joinType = join.getSqmJoinType(); + final var joinType = join.getSqmJoinType(); if ( joinType != requestedJoinType ) { throw new IllegalStateException( String.format( "Requested join fetch with association [%s] with '%s' join type, " + @@ -456,12 +442,12 @@ public static Map, Map, List, Map, List>> result = new IdentityHashMap<>( domainParameterXref.getQueryParameterCount() ); domainParameterXref.getQueryParameters().forEach( (queryParam, sqmParams) -> { - final Map, List> sqmParamMap = + final var sqmParamMap = result.computeIfAbsent( queryParam, qp -> new IdentityHashMap<>( sqmParams.size() ) ); - for ( SqmParameter sqmParam : sqmParams ) { + for ( var sqmParam : sqmParams ) { final var jdbcParamsBySqmParam = jdbcParameterBySqmParameterAccess.getJdbcParamsBySqmParam(); sqmParamMap.put( sqmParam, convert( jdbcParamsBySqmParam.get( sqmParam ) ) ); - for ( SqmParameter expansion : domainParameterXref.getExpansions( sqmParam ) ) { + for ( var expansion : domainParameterXref.getExpansions( sqmParam ) ) { sqmParamMap.put( expansion, convert( jdbcParamsBySqmParam.get( expansion ) ) ); result.put( queryParam, sqmParamMap ); } @@ -556,38 +542,38 @@ private static void createJdbcParameterBinding( QueryParameterImplementor queryParameter, List> sqmParameters, JdbcParameterBindings jdbcParameterBindings) { - final QueryParameterBinding domainParamBinding = domainParamBindings.getBinding( queryParameter ); + final var domainParamBinding = domainParamBindings.getBinding( queryParameter ); final var jdbcParamMap = jdbcParamXref.get( queryParameter ); - for ( SqmParameter sqmParameter : sqmParameters ) { - final MappingModelExpressible resolvedMappingModelType = + for ( var sqmParameter : sqmParameters ) { + final var resolvedMappingModelType = modelResolutionAccess.getResolvedMappingModelType( checkParameter( queryParameter, sqmParameter ) ); if ( resolvedMappingModelType != null ) { domainParamBinding.setType( resolvedMappingModelType ); } - final Bindable parameterType = + final var parameterType = determineParameterType( domainParamBinding, queryParameter, sqmParameters, modelResolutionAccess, session.getFactory() ); - final List jdbcParamsBinds = jdbcParamMap.get( sqmParameter ); + final var jdbcParamsBinds = jdbcParamMap.get( sqmParameter ); if ( jdbcParamsBinds == null ) { // This can happen when a group or order by item expression, that contains parameters, // is replaced with an alias reference expression, which can happen for JPA Criteria queries } else if ( !domainParamBinding.isBound() ) { for ( int i = 0; i < jdbcParamsBinds.size(); i++ ) { - final JdbcParametersList jdbcParams = jdbcParamsBinds.get( i ); + final var jdbcParams = jdbcParamsBinds.get( i ); parameterType.forEachJdbcType( (position, jdbcMapping) -> jdbcParameterBindings.addBinding( jdbcParams.get( position ), new JdbcParameterBindingImpl( jdbcMapping, null ) ) ); } } else if ( domainParamBinding.isMultiValued() ) { - final Collection bindValues = domainParamBinding.getBindValues(); - final Iterator valueIterator = bindValues.iterator(); + final var bindValues = domainParamBinding.getBindValues(); + final var valueIterator = bindValues.iterator(); // the original SqmParameter is the one we are processing - create a binding for it final Object firstValue = valueIterator.next(); for ( int i = 0; i < jdbcParamsBinds.size(); i++ ) { - final JdbcParametersList jdbcParams = jdbcParamsBinds.get( i ); + final var jdbcParams = jdbcParamsBinds.get( i ); createValueBindings( jdbcParameterBindings, queryParameter, @@ -600,7 +586,7 @@ else if ( domainParamBinding.isMultiValued() ) { } // and then one for each of the expansions - final List> expansions = domainParameterXref.getExpansions( sqmParameter ); + final var expansions = domainParameterXref.getExpansions( sqmParameter ); final int expansionCount = bindValues.size() - 1; final int parameterUseCount = jdbcParamsBinds.size(); assert expansions.size() == expansionCount * parameterUseCount; @@ -608,10 +594,10 @@ else if ( domainParamBinding.isMultiValued() ) { while ( valueIterator.hasNext() ) { final Object expandedValue = valueIterator.next(); for ( int j = 0; j < parameterUseCount; j++ ) { - final SqmParameter expansionSqmParam = expansions.get( expansionPosition + j * expansionCount ); - final List jdbcParamBinds = jdbcParamMap.get( expansionSqmParam ); + final var expansionSqmParam = expansions.get( expansionPosition + j * expansionCount ); + final var jdbcParamBinds = jdbcParamMap.get( expansionSqmParam ); for ( int i = 0; i < jdbcParamBinds.size(); i++ ) { - final JdbcParametersList expansionJdbcParams = jdbcParamBinds.get( i ); + final var expansionJdbcParams = jdbcParamBinds.get( i ); createValueBindings( jdbcParameterBindings, queryParameter, @@ -627,16 +613,16 @@ else if ( domainParamBinding.isMultiValued() ) { } } else { - final JdbcMapping jdbcMapping = jdbcMapping( domainParamBinding ); + final var jdbcMapping = jdbcMapping( domainParamBinding ); final BasicValueConverter valueConverter = jdbcMapping == null ? null : jdbcMapping.getValueConverter(); if ( valueConverter != null ) { final Object convertedValue = valueConverter.toRelationalValue( domainParamBinding.getBindValue() ); for ( int i = 0; i < jdbcParamsBinds.size(); i++ ) { - final JdbcParametersList jdbcParams = jdbcParamsBinds.get( i ); + final var jdbcParams = jdbcParamsBinds.get( i ); assert jdbcParams.size() == 1; - final JdbcParameter jdbcParameter = jdbcParams.get( 0 ); + final var jdbcParameter = jdbcParams.get( 0 ); jdbcParameterBindings.addBinding( jdbcParameter, new JdbcParameterBindingImpl( jdbcMapping, convertedValue ) ); } @@ -645,9 +631,9 @@ else if ( domainParamBinding.isMultiValued() ) { final Object bindValue = domainParamBinding.getBindValue(); if ( bindValue == null ) { for ( int i = 0; i < jdbcParamsBinds.size(); i++ ) { - final JdbcParametersList jdbcParams = jdbcParamsBinds.get( i ); + final var jdbcParams = jdbcParamsBinds.get( i ); for ( int j = 0; j < jdbcParams.size(); j++ ) { - final JdbcParameter jdbcParameter = jdbcParams.get( j ); + final var jdbcParameter = jdbcParams.get( j ); jdbcParameterBindings.addBinding( jdbcParameter, new JdbcParameterBindingImpl( jdbcMapping, bindValue ) ); } @@ -655,7 +641,7 @@ else if ( domainParamBinding.isMultiValued() ) { } else { for ( int i = 0; i < jdbcParamsBinds.size(); i++ ) { - final JdbcParametersList jdbcParams = jdbcParamsBinds.get( i ); + final var jdbcParams = jdbcParamsBinds.get( i ); createValueBindings( jdbcParameterBindings, queryParameter, @@ -682,7 +668,7 @@ else if ( domainParamBinding.isMultiValued() ) { assert sqmParameter.getPosition() == null || sqmParameter.getPosition().equals( queryParameter.getPosition() ); @SuppressWarnings("unchecked") // not great! - final SqmParameter checkedSqmParameter = (SqmParameter) sqmParameter; + final var checkedSqmParameter = (SqmParameter) sqmParameter; return checkedSqmParameter; } @@ -806,7 +792,7 @@ public static Bindable determineParameterType( } for ( int i = 0; i < sqmParameters.size(); i++ ) { - final MappingModelExpressible mappingModelType = + final var mappingModelType = mappingModelResolutionAccess.getResolvedMappingModelType( sqmParameters.get( i ) ); if ( mappingModelType != null ) { return mappingModelType; @@ -849,7 +835,7 @@ else if ( object instanceof Bindable bindable ) { public static SqmStatement.ParameterResolutions resolveParameters(SqmStatement statement) { if ( statement.getQuerySource() == SqmQuerySource.CRITERIA ) { - final CriteriaParameterCollector parameterCollector = new CriteriaParameterCollector(); + final var parameterCollector = new CriteriaParameterCollector(); collectParameters( statement, parameterCollector::process ); return parameterCollector.makeResolution(); } @@ -869,14 +855,14 @@ public Map, SqmJpaCriteriaParameterWrapper> getJpaCri } public static SqmSortSpecification sortSpecification(SqmSelectStatement sqm, Order order) { - final List> items = sqm.getQuerySpec().getSelectClause().getSelectionItems(); - final SqmSelectableNode selected = selectedNode( sqm, order ); // does validation by side effect! + final var items = sqm.getQuerySpec().getSelectClause().getSelectionItems(); + final var selected = selectedNode( sqm, order ); // does validation by side effect! return createSortSpecification( sqm, order, items, selected ); } private static SqmSortSpecification createSortSpecification( SqmSelectStatement sqm, Order order, List> items, SqmSelectableNode selected) { - final NodeBuilder builder = sqm.nodeBuilder(); + final var builder = sqm.nodeBuilder(); if ( order.entityClass() == null ) { // ordering by an element of the select list return new SqmSortSpecification( @@ -914,15 +900,16 @@ private static SqmSelectableNode selectedNode(SqmSelectStatement sqm, Orde throw new IllegalQueryOperationException("Cannot order by element " + element + " (the first select item is element 1)"); } - final var selectionItems = sqm.getQuerySpec().getSelectClause().getSelectionItems(); + final var querySpec = sqm.getQuerySpec(); + final var selectionItems = querySpec.getSelectClause().getSelectionItems(); final int items = selectionItems.size(); if ( items == 0 && element == 1 ) { - if ( order.entityClass() == null || sqm.getQuerySpec().getRootList().size() > 1 ) { + if ( order.entityClass() == null || querySpec.getRootList().size() > 1 ) { throw new IllegalQueryOperationException("Cannot order by element " + element + " (there is no select list)"); } else { - return sqm.getQuerySpec().getRootList().get(0); + return querySpec.getRootList().get(0); } } else if ( element > items ) { @@ -939,7 +926,7 @@ public static boolean isSelectionAssignableToResultType(SqmSelection selectio return true; } else if ( selection != null && selection.getSelectableNode() instanceof SqmParameter sqmParameter ) { - final Class anticipatedClass = + final var anticipatedClass = sqmParameter.getAnticipatedType() != null ? sqmParameter.getAnticipatedType().getJavaType() : null; @@ -951,7 +938,7 @@ else if ( selection == null return false; } else { - final JavaType nodeJavaType = selection.getNodeJavaType(); + final var nodeJavaType = selection.getNodeJavaType(); return nodeJavaType != null && expectedResultType.isAssignableFrom( nodeJavaType.getJavaTypeClass() ); } @@ -962,10 +949,14 @@ public static boolean isHqlTuple(SqmSelection selection) { } public static Class resolveExpressibleJavaTypeClass(final SqmExpression expression) { - final SqmExpressible expressible = expression.getExpressible(); - return expressible == null || expressible.getExpressibleJavaType() == null - ? null - : expressible.getExpressibleJavaType().getJavaTypeClass(); + final var expressible = expression.getExpressible(); + if ( expressible == null ) { + return null; + } + else { + final var javaType = expressible.getExpressibleJavaType(); + return javaType == null ? null : javaType.getJavaTypeClass(); + } } public static SqmPredicate restriction( @@ -973,21 +964,22 @@ public static SqmPredicate restriction( Class resultType, Restriction restriction) { //noinspection unchecked - final JpaRoot root = (JpaRoot) sqmStatement.getRoot( 0, resultType ); - return (SqmPredicate) restriction.toPredicate( root, sqmStatement.nodeBuilder() ); + final var root = (JpaRoot) sqmStatement.getRoot( 0, resultType ); + return (SqmPredicate) restriction.toPredicate( root, sqmStatement.nodeBuilder() ); } public static void validateCriteriaQuery(SqmQueryPart queryPart) { if ( queryPart instanceof SqmQuerySpec sqmQuerySpec ) { - if ( sqmQuerySpec.getSelectClause().getSelections().isEmpty() ) { + final var selectClause = sqmQuerySpec.getSelectClause(); + if ( selectClause.getSelections().isEmpty() ) { // make sure there is at least one root - final List> sqmRoots = sqmQuerySpec.getFromClause().getRoots(); + final var sqmRoots = sqmQuerySpec.getFromClause().getRoots(); if ( sqmRoots == null || sqmRoots.isEmpty() ) { throw new IllegalArgumentException( "Criteria did not define any query roots" ); } // if there is a single root, use that as the selection if ( sqmRoots.size() == 1 ) { - sqmQuerySpec.getSelectClause().add( sqmRoots.get( 0 ), null ); + selectClause.add( sqmRoots.get( 0 ), null ); } else { throw new IllegalArgumentException( "Criteria has multiple query roots" ); @@ -995,7 +987,7 @@ public static void validateCriteriaQuery(SqmQueryPart queryPart) { } } else if ( queryPart instanceof SqmQueryGroup queryGroup ) { - for ( SqmQueryPart part : queryGroup.getQueryParts() ) { + for ( var part : queryGroup.getQueryParts() ) { validateCriteriaQuery( part ); } } @@ -1072,15 +1064,14 @@ public ParameterResolutionsImpl( else { this.jpaCriteriaParamResolutions = new IdentityHashMap<>( determineProperSizing( jpaCriteriaParamResolutions ) ); - for ( Map.Entry, List>> entry - : jpaCriteriaParamResolutions.entrySet() ) { - final Iterator> itr = entry.getValue().iterator(); - if ( !itr.hasNext() ) { + for ( var entry : jpaCriteriaParamResolutions.entrySet() ) { + final var iterator = entry.getValue().iterator(); + if ( !iterator.hasNext() ) { throw new IllegalStateException( "SqmJpaCriteriaParameterWrapper references for JpaCriteriaParameter [" + entry.getKey() + "] already exhausted" ); } - this.jpaCriteriaParamResolutions.put( entry.getKey(), itr.next() ); + this.jpaCriteriaParamResolutions.put( entry.getKey(), iterator.next() ); } } } @@ -1115,7 +1106,7 @@ public static void checkQueryReturnType(SqmQueryPart queryPart, Class expe checkQueryReturnType( querySpec, expectedResultType ); } else if ( queryPart instanceof SqmQueryGroup queryGroup ) { - for ( SqmQueryPart sqmQueryPart : queryGroup.getQueryParts() ) { + for ( var sqmQueryPart : queryGroup.getQueryParts() ) { checkQueryReturnType( sqmQueryPart, expectedResultType ); } } @@ -1125,11 +1116,11 @@ else if ( queryPart instanceof SqmQueryGroup queryGroup ) { } private static void checkQueryReturnType(SqmQuerySpec querySpec, Class expectedResultClass) { - final JpaCompliance jpaCompliance = querySpec.nodeBuilder().getJpaCompliance(); - final List> selections = querySpec.getSelectClause().getSelections(); + final var jpaCompliance = querySpec.nodeBuilder().getJpaCompliance(); + final var selections = querySpec.getSelectClause().getSelections(); if ( selections == null || selections.isEmpty() ) { // make sure there is at least one root - final List> sqmRoots = querySpec.getFromClause().getRoots(); + final var sqmRoots = querySpec.getFromClause().getRoots(); if ( sqmRoots == null || sqmRoots.isEmpty() ) { throw new IllegalArgumentException( "Criteria did not define any query roots" ); } @@ -1142,13 +1133,14 @@ private static void checkQueryReturnType(SqmQuerySpec querySpec, Class exp } } else if ( selections.size() == 1 ) { - final SqmSelection sqmSelection = selections.get( 0 ); - final SqmSelectableNode selectableNode = sqmSelection.getSelectableNode(); + final var sqmSelection = selections.get( 0 ); + final var selectableNode = sqmSelection.getSelectableNode(); if ( selectableNode.isCompoundSelection() ) { - final Class expectedSelectItemType = expectedResultClass.isArray() - ? expectedResultClass.getComponentType() - : expectedResultClass; - for ( JpaSelection selection : selectableNode.getSelectionItems() ) { + final var expectedSelectItemType = + expectedResultClass.isArray() + ? expectedResultClass.getComponentType() + : expectedResultClass; + for ( var selection : selectableNode.getSelectionItems() ) { verifySelectionType( expectedSelectItemType, jpaCompliance, (SqmSelectableNode) selection ); } } @@ -1157,8 +1149,8 @@ else if ( selections.size() == 1 ) { } } else if ( expectedResultClass.isArray() ) { - final Class componentType = expectedResultClass.getComponentType(); - for ( SqmSelection selection : selections ) { + final var componentType = expectedResultClass.getComponentType(); + for ( var selection : selections ) { verifySelectionType( componentType, jpaCompliance, selection.getSelectableNode() ); } } @@ -1185,7 +1177,7 @@ private static void verifySingularSelectionType( catch (QueryTypeMismatchException mismatchException) { // Check for special case of a single selection item and implicit instantiation. // See if the selected type can be used to instantiate the expected-type - final JavaType javaTypeDescriptor = selectableNode.getJavaTypeDescriptor(); + final var javaTypeDescriptor = selectableNode.getJavaTypeDescriptor(); if ( javaTypeDescriptor != null ) { // ignore the exception if the expected type has a constructor accepting the selected item type if ( hasMatchingConstructor( expectedResultClass, javaTypeDescriptor.getJavaTypeClass() ) ) { @@ -1214,7 +1206,7 @@ private static void verifySelectionType( SqmSelectableNode selection) { // special case for parameters in the select list if ( selection instanceof SqmParameter sqmParameter ) { - final SqmExpressible nodeType = sqmParameter.getExpressible(); + final var nodeType = sqmParameter.getExpressible(); // we may not yet know a selection type if ( nodeType == null || nodeType.getExpressibleJavaType() == null ) { // we can't verify the result type up front @@ -1245,13 +1237,13 @@ public static boolean isResultTypeAlwaysAllowed(Class expectedResultClass) { } protected static void verifyResultType(Class resultClass, SqmSelectableNode selectableNode) { - final SqmBindableType selectionExpressible = selectableNode.getExpressible(); - final JavaType javaType = + final var selectionExpressible = selectableNode.getExpressible(); + final var javaType = selectionExpressible == null ? selectableNode.getNodeJavaType() // for SqmDynamicInstantiation : selectionExpressible.getExpressibleJavaType(); if ( javaType != null ) { - final Class javaTypeClass = javaType.getJavaTypeClass(); + final var javaTypeClass = javaType.getJavaTypeClass(); if ( javaTypeClass != Object.class ) { if ( !isValid( resultClass, selectionExpressible, javaTypeClass, javaType ) ) { throwQueryTypeMismatchException( resultClass, selectionExpressible, javaTypeClass ); @@ -1332,11 +1324,11 @@ private static void throwQueryTypeMismatchException( } public static Set> getParameters(SqmStatement statement) { - final Set> parameters = statement.getSqmParameters(); + final var parameters = statement.getSqmParameters(); return switch ( parameters.size() ) { case 0 -> emptySet(); case 1 -> { - final SqmParameter parameter = parameters.iterator().next(); + final var parameter = parameters.iterator().next(); yield parameter instanceof ValueBindJpaCriteriaParameter ? emptySet() : singleton( parameter ); @@ -1344,7 +1336,7 @@ public static Set> getParameters(SqmStatement statemen default -> { final Set> parameterExpressions = new HashSet<>( parameters.size() ); - for ( SqmParameter parameter : parameters ) { + for ( var parameter : parameters ) { if ( !(parameter instanceof ValueBindJpaCriteriaParameter) ) { parameterExpressions.add( parameter ); }