refactor some functionality out of constructor SessionFactoryImpl into observers

This commit is contained in:
Gavin 2023-01-02 13:29:43 +01:00 committed by Gavin King
parent 7aa92a7c05
commit 102ef2f469
11 changed files with 273 additions and 170 deletions

View File

@ -41,7 +41,6 @@ import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.boot.spi.SessionFactoryBuilderFactory;
import org.hibernate.boot.spi.SessionFactoryBuilderImplementor;
import org.hibernate.boot.spi.SessionFactoryBuilderService;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -72,6 +71,8 @@ import org.hibernate.tool.schema.Action;
import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator;
import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.cfg.AvailableSettings.EVENT_LISTENER_PREFIX;
/**
* Container for configuration data collected during binding the metamodel.
*
@ -523,8 +524,8 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
for ( Map.Entry<String,Object> entry : cfgService.getSettings().entrySet() ) {
final String propertyName = entry.getKey();
if ( propertyName.startsWith( AvailableSettings.EVENT_LISTENER_PREFIX ) ) {
final String eventTypeName = propertyName.substring( AvailableSettings.EVENT_LISTENER_PREFIX.length() + 1 );
if ( propertyName.startsWith( EVENT_LISTENER_PREFIX ) ) {
final String eventTypeName = propertyName.substring( EVENT_LISTENER_PREFIX.length() + 1 );
final EventType<?> eventType = EventType.resolveEventTypeByName( eventTypeName );
final String listeners = (String) entry.getValue();
appendListeners( eventListenerRegistry, classLoaderService, listeners, eventType );

View File

@ -16,7 +16,6 @@ import org.hibernate.SessionFactory;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.TempTableDdlTransactionHandling;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.boot.spi.SessionFactoryBuilderImplementor;
@ -54,11 +53,20 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
public SessionFactoryBuilderImpl(MetadataImplementor metadata, SessionFactoryOptionsBuilder optionsBuilder) {
this.metadata = metadata;
this.optionsBuilder = optionsBuilder;
if ( metadata.getSqlFunctionMap() != null ) {
for ( Map.Entry<String, SqmFunctionDescriptor> sqlFunctionEntry : metadata.getSqlFunctionMap().entrySet() ) {
applySqlFunction( sqlFunctionEntry.getKey(), sqlFunctionEntry.getValue() );
}
}
final BytecodeProvider bytecodeProvider =
metadata.getMetadataBuildingOptions().getServiceRegistry()
.getService( BytecodeProvider.class );
addSessionFactoryObservers( new SessionFactoryObserverForBytecodeEnhancer( bytecodeProvider ) );
addSessionFactoryObservers( new SessionFactoryObserverForNamedQueryValidation( metadata ) );
addSessionFactoryObservers( new SessionFactoryObserverForSchemaExport( metadata ) );
addSessionFactoryObservers( new SessionFactoryObserverForRegistration() );
}
@Override
@ -409,9 +417,6 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
@Override
public SessionFactory build() {
final StandardServiceRegistry serviceRegistry = metadata.getMetadataBuildingOptions().getServiceRegistry();
BytecodeProvider bytecodeProvider = serviceRegistry.getService( BytecodeProvider.class );
addSessionFactoryObservers( new SessionFactoryObserverForBytecodeEnhancer( bytecodeProvider ) );
return new SessionFactoryImpl( metadata, buildSessionFactoryOptions() );
}

View File

@ -0,0 +1,42 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.boot.internal;
import org.hibernate.SessionFactory;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.spi.QueryEngine;
/**
* Responsible for triggering {@linkplain QueryEngine#validateNamedQueries()
* named query validation} when the {@link SessionFactory} is created.
*
* @implNote This was added in order to clean up the constructor of
* {@link org.hibernate.internal.SessionFactoryImpl}, which
* was doing too many things.
*
* @author Gavin King
*/
class SessionFactoryObserverForNamedQueryValidation implements SessionFactoryObserver {
private final Metadata metadata;
SessionFactoryObserverForNamedQueryValidation(MetadataImplementor metadata) {
this.metadata = metadata;
}
@Override
public void sessionFactoryCreated(SessionFactory factory) {
SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) factory;
final QueryEngine queryEngine = sessionFactory.getQueryEngine();
queryEngine.prepare( sessionFactory, metadata );
if ( sessionFactory.getSessionFactoryOptions().isNamedQueryStartupCheckingEnabled() ) {
queryEngine.validateNamedQueries();
}
}
}

View File

@ -0,0 +1,54 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.boot.internal;
import org.hibernate.SessionFactory;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.engine.jndi.spi.JndiService;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.SessionFactoryRegistry;
/**
* Responsible for registering and de-registering the {@link SessionFactory}
* with the {@link SessionFactoryRegistry}.
*
* @implNote This was added in order to clean up the constructor of
* {@link org.hibernate.internal.SessionFactoryImpl}, which
* was doing too many things.
*
* @author Gavin King
*/
class SessionFactoryObserverForRegistration implements SessionFactoryObserver {
private JndiService jndiService;
private boolean registeredInJndi;
@Override
public void sessionFactoryCreated(SessionFactory factory) {
final SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) factory;
jndiService = sessionFactory.getServiceRegistry().getService( JndiService.class );
registeredInJndi = sessionFactory.getSessionFactoryOptions().isSessionFactoryNameAlsoJndiName();
SessionFactoryRegistry.INSTANCE.addSessionFactory(
sessionFactory.getUuid(),
sessionFactory.getName(),
registeredInJndi,
sessionFactory,
jndiService
);
}
@Override
public void sessionFactoryClosed(SessionFactory factory) {
final SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) factory;
SessionFactoryRegistry.INSTANCE.removeSessionFactory(
sessionFactory.getUuid(),
sessionFactory.getName(),
registeredInJndi,
jndiService
);
}
}

View File

@ -0,0 +1,55 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.boot.internal;
import org.hibernate.SessionFactory;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.tool.schema.spi.DelayedDropAction;
import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator;
/**
* Responsible for calling the {@link SchemaManagementToolCoordinator}
* when the {@link SessionFactory} is created and destroyed.
*
* @implNote This was added in order to clean up the constructor of
* {@link org.hibernate.internal.SessionFactoryImpl}, which
* was doing too many things.
*
* @author Gavin King
*/
class SessionFactoryObserverForSchemaExport implements SessionFactoryObserver {
private final MetadataImplementor metadata;
private DelayedDropAction delayedDropAction;
SessionFactoryObserverForSchemaExport(MetadataImplementor metadata) {
this.metadata = metadata;
}
@Override
public void sessionFactoryCreated(SessionFactory factory) {
SchemaManagementToolCoordinator.process(
metadata,
getRegistry( factory ),
factory.getProperties(),
action -> delayedDropAction = action
);
}
@Override
public void sessionFactoryClosing(SessionFactory factory) {
if ( delayedDropAction != null ) {
delayedDropAction.perform( getRegistry( factory ) );
}
}
private static ServiceRegistryImplementor getRegistry(SessionFactory factory) {
return ( (SessionFactoryImplementor) factory ).getServiceRegistry();
}
}

View File

@ -39,7 +39,6 @@ import org.hibernate.cache.spi.TimestampsCacheFactory;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.config.internal.ConfigurationServiceImpl;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
@ -49,7 +48,6 @@ import org.hibernate.internal.BaselineSessionEventsListenerBuilder;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.EmptyInterceptor;
import org.hibernate.internal.util.NullnessHelper;
import org.hibernate.internal.util.PropertiesHelper;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.jpa.spi.JpaCompliance;
import org.hibernate.jpa.spi.MutableJpaCompliance;
@ -67,7 +65,6 @@ import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.hibernate.resource.jdbc.spi.StatementInspector;
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.stat.Statistics;
import org.hibernate.type.format.FormatMapper;
import org.hibernate.type.format.jackson.JacksonIntegration;
@ -130,6 +127,7 @@ import static org.hibernate.cfg.AvailableSettings.USE_STRUCTURED_CACHE;
import static org.hibernate.engine.config.spi.StandardConverters.BOOLEAN;
import static org.hibernate.internal.CoreLogging.messageLogger;
import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER;
import static org.hibernate.internal.util.PropertiesHelper.map;
import static org.hibernate.internal.util.StringHelper.isEmpty;
import static org.hibernate.internal.util.config.ConfigurationHelper.extractPropertyValue;
import static org.hibernate.internal.util.config.ConfigurationHelper.getBoolean;
@ -138,12 +136,12 @@ import static org.hibernate.internal.util.config.ConfigurationHelper.getInteger;
import static org.hibernate.internal.util.config.ConfigurationHelper.getString;
/**
* In-flight state of {@link SessionFactoryOptions}
* during {@link org.hibernate.boot.SessionFactoryBuilder} processing.
*
* The intention is that {@code SessionFactoryBuilder} internally creates and populates
* this builder, which is then used to construct the {@code SessionFactoryOptions}
* as part of building the {@code SessionFactory} ({@link org.hibernate.boot.SessionFactoryBuilder#build})
* In-flight state of {@link SessionFactoryOptions} during {@link org.hibernate.boot.SessionFactoryBuilder}
* processing.
* <p>
* The intention is that {@code SessionFactoryBuilder} internally creates and populates this builder, which
* is then used to construct the {@code SessionFactoryOptions} as part of building the {@code SessionFactory}
* from {@link org.hibernate.boot.SessionFactoryBuilder#build}.
*
* @author Steve Ebersole
*/
@ -156,11 +154,11 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
// integration
private Object beanManagerReference;
private Object validatorFactoryReference;
private FormatMapper jsonFormatMapper;
private FormatMapper xmlFormatMapper;
private final FormatMapper jsonFormatMapper;
private final FormatMapper xmlFormatMapper;
// SessionFactory behavior
private boolean jpaBootstrap;
private final boolean jpaBootstrap;
private String sessionFactoryName;
private boolean sessionFactoryNameAlsoJndiName;
@ -179,7 +177,6 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
// Statistics/Interceptor/observers
private boolean statisticsEnabled;
private Interceptor interceptor;
private Class<? extends Interceptor> statelessInterceptorClass;
private Supplier<? extends Interceptor> statelessInterceptorSupplier;
private StatementInspector statementInspector;
private final List<SessionFactoryObserver> sessionFactoryObserverList = new ArrayList<>();
@ -200,23 +197,22 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
private NullPrecedence defaultNullPrecedence;
private boolean orderUpdatesEnabled;
private boolean orderInsertsEnabled;
private boolean postInsertIdentifierDelayed;
private boolean collectionsInDefaultFetchGroupEnabled = true;
// JPA callbacks
private boolean callbacksEnabled;
private final boolean callbacksEnabled;
// multi-tenancy
private boolean multiTenancyEnabled;
private CurrentTenantIdentifierResolver currentTenantIdentifierResolver;
// Queries
private HqlTranslator hqlTranslator;
private SqmMultiTableMutationStrategy sqmMultiTableMutationStrategy;
private SqmMultiTableInsertStrategy sqmMultiTableInsertStrategy;
private SqmFunctionRegistry sqmFunctionRegistry;
private SqmTranslatorFactory sqmTranslatorFactory;
private Boolean useOfJdbcNamedParametersEnabled;
private final HqlTranslator hqlTranslator;
private final SqmMultiTableMutationStrategy sqmMultiTableMutationStrategy;
private final SqmMultiTableInsertStrategy sqmMultiTableInsertStrategy;
private final SqmTranslatorFactory sqmTranslatorFactory;
private final Boolean useOfJdbcNamedParametersEnabled;
private boolean namedQueryStartupCheckingEnabled;
private final int preferredSqlTypeCodeForBoolean;
private final int preferredSqlTypeCodeForDuration;
@ -248,9 +244,9 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
private PhysicalConnectionHandlingMode connectionHandlingMode;
private boolean connectionProviderDisablesAutoCommit;
private TimeZone jdbcTimeZone;
private ValueHandlingMode criteriaValueHandlingMode;
private boolean criteriaCopyTreeEnabled;
private ImmutableEntityUpdateQueryHandlingMode immutableEntityUpdateQueryHandlingMode;
private final ValueHandlingMode criteriaValueHandlingMode;
private final boolean criteriaCopyTreeEnabled;
private final ImmutableEntityUpdateQueryHandlingMode immutableEntityUpdateQueryHandlingMode;
// These two settings cannot be modified from the builder,
// in order to maintain consistency.
// Indeed, other components (the schema tools) also make use of these settings,
@ -262,10 +258,10 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
private JpaCompliance jpaCompliance;
private boolean failOnPaginationOverCollectionFetchEnabled;
private boolean inClauseParameterPaddingEnabled;
private final boolean failOnPaginationOverCollectionFetchEnabled;
private final boolean inClauseParameterPaddingEnabled;
private int queryStatisticsMaxSize;
private final int queryStatisticsMaxSize;
public SessionFactoryOptionsBuilder(StandardServiceRegistry serviceRegistry, BootstrapContext context) {
@ -273,16 +269,12 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
this.jpaBootstrap = context.isJpaBootstrap();
final StrategySelector strategySelector = serviceRegistry.getService( StrategySelector.class );
ConfigurationService cfgService = serviceRegistry.getService( ConfigurationService.class );
final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class );
final JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class );
final Map<String,Object> configurationSettings = new HashMap<>();
configurationSettings.putAll( PropertiesHelper.map( jdbcServices.getJdbcEnvironment().getDialect().getDefaultProperties() ) );
configurationSettings.putAll( cfgService.getSettings() );
if ( cfgService == null ) {
cfgService = new ConfigurationServiceImpl( configurationSettings );
( (ConfigurationServiceImpl) cfgService ).injectServices( (ServiceRegistryImplementor) serviceRegistry );
}
configurationSettings.putAll( map( jdbcServices.getJdbcEnvironment().getDialect().getDefaultProperties() ) );
configurationSettings.putAll( configurationService.getSettings() );
this.beanManagerReference = NullnessHelper.coalesceSuppliedValues(
() -> configurationSettings.get( AvailableSettings.JAKARTA_CDI_BEAN_MANAGER ),
@ -312,27 +304,27 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
);
this.sessionFactoryName = (String) configurationSettings.get( SESSION_FACTORY_NAME );
this.sessionFactoryNameAlsoJndiName = cfgService.getSetting(
this.sessionFactoryNameAlsoJndiName = configurationService.getSetting(
SESSION_FACTORY_NAME_IS_JNDI,
BOOLEAN,
true
);
this.jtaTransactionAccessEnabled = cfgService.getSetting(
this.jtaTransactionAccessEnabled = configurationService.getSetting(
ALLOW_JTA_TRANSACTION_ACCESS,
BOOLEAN,
true
);
this.allowRefreshDetachedEntity = cfgService.getSetting(
this.allowRefreshDetachedEntity = configurationService.getSetting(
ALLOW_REFRESH_DETACHED_ENTITY,
BOOLEAN,
true
);
this.flushBeforeCompletionEnabled = cfgService.getSetting( FLUSH_BEFORE_COMPLETION, BOOLEAN, true );
this.autoCloseSessionEnabled = cfgService.getSetting( AUTO_CLOSE_SESSION, BOOLEAN, false );
this.flushBeforeCompletionEnabled = configurationService.getSetting( FLUSH_BEFORE_COMPLETION, BOOLEAN, true );
this.autoCloseSessionEnabled = configurationService.getSetting( AUTO_CLOSE_SESSION, BOOLEAN, false );
this.statisticsEnabled = cfgService.getSetting( GENERATE_STATISTICS, BOOLEAN, false );
this.statisticsEnabled = configurationService.getSetting( GENERATE_STATISTICS, BOOLEAN, false );
this.interceptor = determineInterceptor( configurationSettings, strategySelector );
this.statelessInterceptorSupplier = determineStatelessInterceptor( configurationSettings, strategySelector );
this.statementInspector = strategySelector.resolveStrategy(
@ -341,14 +333,12 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
);
// todo : expose this from builder?
final String autoSessionEventsListenerName = (String) configurationSettings.get(
AUTO_SESSION_EVENTS_LISTENER
);
final String autoSessionEventsListenerName = (String) configurationSettings.get( AUTO_SESSION_EVENTS_LISTENER );
final Class<? extends SessionEventListener> autoSessionEventsListener = autoSessionEventsListenerName == null
? null
: strategySelector.selectStrategyImplementor( SessionEventListener.class, autoSessionEventsListenerName );
final boolean logSessionMetrics = cfgService.getSetting( LOG_SESSION_METRICS, BOOLEAN, statisticsEnabled );
final boolean logSessionMetrics = configurationService.getSetting( LOG_SESSION_METRICS, BOOLEAN, statisticsEnabled );
this.baselineSessionEventsListenerBuilder = new BaselineSessionEventsListenerBuilder( logSessionMetrics, autoSessionEventsListener );
this.customEntityDirtinessStrategy = strategySelector.resolveDefaultableStrategy(
@ -358,9 +348,9 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
);
this.entityNotFoundDelegate = StandardEntityNotFoundDelegate.INSTANCE;
this.identifierRollbackEnabled = cfgService.getSetting( USE_IDENTIFIER_ROLLBACK, BOOLEAN, false );
this.checkNullability = cfgService.getSetting( CHECK_NULLABILITY, BOOLEAN, true );
this.initializeLazyStateOutsideTransactions = cfgService.getSetting( ENABLE_LAZY_LOAD_NO_TRANS, BOOLEAN, false );
this.identifierRollbackEnabled = configurationService.getSetting( USE_IDENTIFIER_ROLLBACK, BOOLEAN, false );
this.checkNullability = configurationService.getSetting( CHECK_NULLABILITY, BOOLEAN, true );
this.initializeLazyStateOutsideTransactions = configurationService.getSetting( ENABLE_LAZY_LOAD_NO_TRANS, BOOLEAN, false );
this.multiTenancyEnabled = serviceRegistry.getService(MultiTenantConnectionProvider.class)!=null;
this.currentTenantIdentifierResolver = strategySelector.resolveStrategy(
@ -369,7 +359,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
);
this.batchFetchStyle = BatchFetchStyle.interpret( configurationSettings.get( BATCH_FETCH_STYLE ) );
this.delayBatchFetchLoaderCreations = cfgService.getSetting( DELAY_ENTITY_LOADER_CREATIONS, BOOLEAN, true );
this.delayBatchFetchLoaderCreations = configurationService.getSetting( DELAY_ENTITY_LOADER_CREATIONS, BOOLEAN, true );
this.defaultBatchFetchSize = getInt( DEFAULT_BATCH_FETCH_SIZE, configurationSettings, -1 );
this.maximumFetchDepth = getInteger( MAX_FETCH_DEPTH, configurationSettings );
final String defaultNullPrecedence = getString(
@ -381,7 +371,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
this.callbacksEnabled = getBoolean( JPA_CALLBACKS_ENABLED, configurationSettings, true );
this.jtaTrackByThread = cfgService.getSetting( JTA_TRACK_BY_THREAD, BOOLEAN, true );
this.jtaTrackByThread = configurationService.getSetting( JTA_TRACK_BY_THREAD, BOOLEAN, true );
final String hqlTranslatorImplFqn = extractPropertyValue(
AvailableSettings.SEMANTIC_QUERY_PRODUCER,
@ -426,9 +416,9 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
strategySelector
);
this.useOfJdbcNamedParametersEnabled = cfgService.getSetting( CALLABLE_NAMED_PARAMS_ENABLED, BOOLEAN, true );
this.useOfJdbcNamedParametersEnabled = configurationService.getSetting( CALLABLE_NAMED_PARAMS_ENABLED, BOOLEAN, true );
this.namedQueryStartupCheckingEnabled = cfgService.getSetting( QUERY_STARTUP_CHECKING, BOOLEAN, true );
this.namedQueryStartupCheckingEnabled = configurationService.getSetting( QUERY_STARTUP_CHECKING, BOOLEAN, true );
this.preferredSqlTypeCodeForBoolean = ConfigurationHelper.getPreferredSqlTypeCodeForBoolean( serviceRegistry );
this.preferredSqlTypeCodeForDuration = ConfigurationHelper.getPreferredSqlTypeCodeForDuration( serviceRegistry );
this.preferredSqlTypeCodeForUuid = ConfigurationHelper.getPreferredSqlTypeCodeForUuid( serviceRegistry );
@ -438,8 +428,8 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
final RegionFactory regionFactory = serviceRegistry.getService( RegionFactory.class );
if ( !(regionFactory instanceof NoCachingRegionFactory) ) {
this.secondLevelCacheEnabled = cfgService.getSetting( USE_SECOND_LEVEL_CACHE, BOOLEAN, true );
this.queryCacheEnabled = cfgService.getSetting( USE_QUERY_CACHE, BOOLEAN, false );
this.secondLevelCacheEnabled = configurationService.getSetting( USE_SECOND_LEVEL_CACHE, BOOLEAN, true );
this.queryCacheEnabled = configurationService.getSetting( USE_QUERY_CACHE, BOOLEAN, false );
this.timestampsCacheFactory = strategySelector.resolveDefaultableStrategy(
TimestampsCacheFactory.class,
configurationSettings.get( QUERY_CACHE_FACTORY ),
@ -449,18 +439,18 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
CACHE_REGION_PREFIX,
configurationSettings
);
this.minimalPutsEnabled = cfgService.getSetting(
this.minimalPutsEnabled = configurationService.getSetting(
USE_MINIMAL_PUTS,
BOOLEAN,
regionFactory.isMinimalPutsEnabledByDefault()
);
this.structuredCacheEntriesEnabled = cfgService.getSetting( USE_STRUCTURED_CACHE, BOOLEAN, false );
this.directReferenceCacheEntriesEnabled = cfgService.getSetting(
this.structuredCacheEntriesEnabled = configurationService.getSetting( USE_STRUCTURED_CACHE, BOOLEAN, false );
this.directReferenceCacheEntriesEnabled = configurationService.getSetting(
USE_DIRECT_REFERENCE_CACHE_ENTRIES,
BOOLEAN,
false
);
this.autoEvictCollectionCache = cfgService.getSetting( AUTO_EVICT_COLLECTION_CACHE, BOOLEAN, false );
this.autoEvictCollectionCache = configurationService.getSetting( AUTO_EVICT_COLLECTION_CACHE, BOOLEAN, false );
}
else {
this.secondLevelCacheEnabled = false;
@ -1284,7 +1274,6 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
}
public void applyStatelessInterceptor(Class<? extends Interceptor> statelessInterceptorClass) {
this.statelessInterceptorClass = statelessInterceptorClass;
this.applyStatelessInterceptorSupplier(
() -> {
try {
@ -1369,10 +1358,6 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
this.orderUpdatesEnabled = enabled;
}
public void enableDelayedIdentityInserts(boolean enabled) {
this.postInsertIdentifierDelayed = enabled;
}
public void applyMultiTenancy(boolean enabled) {
this.multiTenancyEnabled = enabled;
}

View File

@ -42,7 +42,6 @@ import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.boot.model.relational.internal.SqlStringGenerationContextImpl;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cache.cfg.internal.DomainDataRegionConfigImpl;
@ -59,7 +58,6 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jndi.spi.JndiService;
import org.hibernate.engine.profile.Association;
import org.hibernate.engine.profile.Fetch;
import org.hibernate.engine.profile.FetchProfile;
@ -93,7 +91,6 @@ import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.SessionFactoryBasedWrapperOptions;
import org.hibernate.procedure.spi.ProcedureCallImplementor;
import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.query.BindableType;
import org.hibernate.query.hql.spi.SqmQueryImplementor;
@ -115,8 +112,6 @@ import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
import org.hibernate.service.spi.SessionFactoryServiceRegistryFactory;
import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.tool.schema.spi.DelayedDropAction;
import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.spi.TypeConfiguration;
@ -129,6 +124,7 @@ import jakarta.persistence.PersistenceUnitUtil;
import jakarta.persistence.Query;
import jakarta.persistence.SynchronizationType;
import static jakarta.persistence.SynchronizationType.SYNCHRONIZED;
import static java.util.Collections.emptySet;
import static java.util.Collections.unmodifiableSet;
import static org.hibernate.cfg.AvailableSettings.CREATE_EMPTY_COMPOSITES_ENABLED;
@ -136,7 +132,8 @@ import static org.hibernate.cfg.AvailableSettings.CURRENT_SESSION_CONTEXT_CLASS;
import static org.hibernate.cfg.AvailableSettings.JAKARTA_VALIDATION_FACTORY;
import static org.hibernate.cfg.AvailableSettings.JPA_VALIDATION_FACTORY;
import static org.hibernate.internal.util.config.ConfigurationHelper.getBoolean;
import static org.hibernate.query.QueryLogging.QUERY_MESSAGE_LOGGER;
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
import static org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT;
/**
* Concrete implementation of the {@link SessionFactory} API.
@ -185,8 +182,6 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
private final transient CurrentSessionContext currentSessionContext;
private volatile DelayedDropAction delayedDropAction;
// todo : move to MetamodelImpl
private final transient Map<String, Generator> identifierGenerators;
private final transient Map<String, FilterDefinition> filters;
@ -205,8 +200,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
LOG.debug( "Building session factory" );
final TypeConfiguration typeConfiguration = bootMetamodel.getTypeConfiguration();
final MetadataBuildingContext bootModelBuildingContext = typeConfiguration.getMetadataBuildingContext();
final BootstrapContext bootstrapContext = bootModelBuildingContext.getBootstrapContext();
final BootstrapContext bootstrapContext = typeConfiguration.getMetadataBuildingContext().getBootstrapContext();
sessionFactoryOptions = options;
@ -329,15 +323,6 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
}
};
queryEngine.prepare( this, bootMetamodel, bootstrapContext );
if ( options.isNamedQueryStartupCheckingEnabled() ) {
checkNamedQueries( queryEngine );
}
exportSchema( bootMetamodel );
currentSessionContext = buildCurrentSessionContext();
// this needs to happen after persisters are all ready to go...
fetchProfiles = getFetchProfiles( bootMetamodel, runtimeMetamodelsImpl );
@ -347,9 +332,9 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
fastSessionServices = new FastSessionServices( this );
wrapperOptions = new SessionFactoryBasedWrapperOptions( this );
observer.sessionFactoryCreated( this );
currentSessionContext = buildCurrentSessionContext();
addToRegistry();
observer.sessionFactoryCreated( this );
// As last operation, delete all caches from ReflectionManager
// (not modelled as a listener as we want this to be last)
@ -371,15 +356,6 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
LOG.debug( "Instantiated SessionFactory" );
}
private void exportSchema(MetadataImplementor bootMetamodel) {
SchemaManagementToolCoordinator.process(
bootMetamodel,
serviceRegistry,
settings,
action -> delayedDropAction = action
);
}
private static Map<String, Generator> createGenerators(
JdbcServices jdbcServices,
SqlStringGenerationContext sqlStringGenerationContext,
@ -425,16 +401,6 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
.buildServiceRegistry( self, options );
}
private void addToRegistry() {
SessionFactoryRegistry.INSTANCE.addSessionFactory(
getUuid(),
name,
sessionFactoryOptions.isSessionFactoryNameAlsoJndiName(),
this,
serviceRegistry.getService( JndiService.class )
);
}
class IntegratorObserver implements SessionFactoryObserver {
private final ArrayList<Integrator> integrators = new ArrayList<>();
@ -483,16 +449,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
final FetchProfile fetchProfile = new FetchProfile( mappingProfile.getName() );
for ( org.hibernate.mapping.FetchProfile.Fetch mappingFetch : mappingProfile.getFetches() ) {
// resolve the persister owning the fetch
final String entityName = runtimeMetamodels.getImportedName( mappingFetch.getEntity() );
final EntityPersister owner = entityName == null
? null
: runtimeMetamodels.getMappingMetamodel().getEntityDescriptor( entityName );
if ( owner == null ) {
throw new HibernateException(
"Unable to resolve entity reference [" + mappingFetch.getEntity()
+ "] in fetch profile [" + fetchProfile.getName() + "]"
);
}
final EntityPersister owner = getEntityPersister( runtimeMetamodels, fetchProfile, mappingFetch );
// validate the specified association fetch
final Type associationType = owner.getPropertyType( mappingFetch.getAssociation() );
@ -510,21 +467,16 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
return fetchProfile;
}
private void checkNamedQueries(QueryEngine queryEngine) {
final Map<String, HibernateException> errors =
queryEngine.getNamedObjectRepository().checkNamedQueries( queryEngine );
if ( !errors.isEmpty() ) {
final StringBuilder failingQueries = new StringBuilder( "Errors in named queries: " );
String sep = "";
for ( Map.Entry<String, HibernateException> entry : errors.entrySet() ) {
QUERY_MESSAGE_LOGGER.namedQueryError( entry.getKey(), entry.getValue() );
failingQueries.append( sep ).append( entry.getKey() );
sep = ", ";
private static EntityPersister getEntityPersister(RuntimeMetamodelsImpl runtimeMetamodels, FetchProfile fetchProfile, org.hibernate.mapping.FetchProfile.Fetch mappingFetch) {
final String entityName = runtimeMetamodels.getImportedName( mappingFetch.getEntity() );
if ( entityName != null ) {
EntityPersister persister = runtimeMetamodels.getMappingMetamodel().getEntityDescriptor( entityName );
if ( persister != null ) {
return persister;
}
final HibernateException exception = new HibernateException( failingQueries.toString() );
errors.values().forEach( exception::addSuppressed );
throw exception;
}
throw new HibernateException( "Unable to resolve entity reference [" + mappingFetch.getEntity()
+ "] in fetch profile [" + fetchProfile.getName() + "]" );
}
private static Map<String, Object> getSettings(SessionFactoryOptions options, SessionFactoryServiceRegistry serviceRegistry) {
@ -563,7 +515,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
return withOptions()
.autoClose( false )
.flushMode( FlushMode.MANUAL )
.connectionHandlingMode( PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT );
.connectionHandlingMode( DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT );
}
private void primeSecondLevelCacheRegions(MetadataImplementor mappingMetadata) {
@ -729,8 +681,8 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
@Override @Deprecated
public DeserializationResolver<?> getDeserializationResolver() {
return () -> (SessionFactoryImplementor) SessionFactoryRegistry.INSTANCE
.findSessionFactory( uuid, name );
return () -> (SessionFactoryImplementor)
SessionFactoryRegistry.INSTANCE.findSessionFactory( uuid, name );
}
@Override @SuppressWarnings({"rawtypes","unchecked"})
@ -743,14 +695,14 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
@Override
public Session createEntityManager() {
validateNotClosed();
return buildEntityManager( SynchronizationType.SYNCHRONIZED, null );
return buildEntityManager( SYNCHRONIZED, null );
}
private <K,V> Session buildEntityManager(final SynchronizationType synchronizationType, final Map<K,V> map) {
assert status != Status.CLOSED;
SessionBuilderImplementor builder = withOptions();
builder.autoJoinTransactions( synchronizationType == SynchronizationType.SYNCHRONIZED );
builder.autoJoinTransactions( synchronizationType == SYNCHRONIZED );
final Session session = builder.openSession();
if ( map != null ) {
@ -768,7 +720,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
@Override @SuppressWarnings("unchecked")
public Session createEntityManager(Map map) {
validateNotClosed();
return buildEntityManager( SynchronizationType.SYNCHRONIZED, map );
return buildEntityManager( SYNCHRONIZED, map );
}
@Override
@ -821,7 +773,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
@Override
public String bestGuessEntityName(Object object) {
final LazyInitializer initializer = HibernateProxy.extractLazyInitializer( object );
final LazyInitializer initializer = extractLazyInitializer( object );
if ( initializer != null ) {
// it is possible for this method to be called during flush processing,
// so make certain that we do not accidentally initialize an uninitialized proxy
@ -933,17 +885,6 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
if ( queryEngine != null ) {
queryEngine.close();
}
if ( delayedDropAction != null ) {
delayedDropAction.perform( serviceRegistry );
}
SessionFactoryRegistry.INSTANCE.removeSessionFactory(
getUuid(),
name,
sessionFactoryOptions.isSessionFactoryNameAlsoJndiName(),
serviceRegistry.getService( JndiService.class )
);
}
finally {
status = Status.CLOSED;
@ -1198,7 +1139,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
return null;
}
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( bindValue );
final LazyInitializer lazyInitializer = extractLazyInitializer( bindValue );
final Class<?> clazz = lazyInitializer != null ? lazyInitializer.getPersistentClass() : bindValue.getClass();
// Resolve superclass bindable type if necessary, as we don't register types for e.g. Inet4Address

View File

@ -11,10 +11,10 @@ import java.util.Map;
import java.util.function.Consumer;
import org.hibernate.HibernateException;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.query.NamedHqlQueryDefinition;
import org.hibernate.boot.query.NamedNativeQueryDefinition;
import org.hibernate.boot.query.NamedProcedureCallDefinition;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
@ -28,6 +28,8 @@ import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
import org.jboss.logging.Logger;
import static org.hibernate.query.QueryLogging.QUERY_MESSAGE_LOGGER;
/**
* @author Steve Ebersole
*/
@ -170,10 +172,7 @@ public class NamedObjectRepositoryImpl implements NamedObjectRepository {
}
@Override
public void prepare(
SessionFactoryImplementor sessionFactory,
MetadataImplementor bootMetamodel,
BootstrapContext bootstrapContext) {
public void prepare(SessionFactoryImplementor sessionFactory, Metadata bootMetamodel) {
bootMetamodel.visitNamedHqlQueryDefinitions(
namedHqlQueryDefinition -> {
final NamedSqmQueryMemento resolved = namedHqlQueryDefinition.resolve( sessionFactory );
@ -208,6 +207,22 @@ public class NamedObjectRepositoryImpl implements NamedObjectRepository {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Named query checking
public void validateNamedQueries(QueryEngine queryEngine) {
final Map<String, HibernateException> errors = checkNamedQueries( queryEngine );
if ( !errors.isEmpty() ) {
final StringBuilder failingQueries = new StringBuilder( "Errors in named queries: " );
String sep = "";
for ( Map.Entry<String, HibernateException> entry : errors.entrySet() ) {
QUERY_MESSAGE_LOGGER.namedQueryError( entry.getKey(), entry.getValue() );
failingQueries.append( sep ).append( entry.getKey() );
sep = ", ";
}
final HibernateException exception = new HibernateException( failingQueries.toString() );
errors.values().forEach( exception::addSuppressed );
throw exception;
}
}
public Map<String, HibernateException> checkNamedQueries(QueryEngine queryEngine) {
Map<String,HibernateException> errors = new HashMap<>();

View File

@ -11,7 +11,7 @@ import java.util.function.Consumer;
import org.hibernate.HibernateException;
import org.hibernate.Incubating;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
@ -71,6 +71,11 @@ public interface NamedObjectRepository {
*/
Map<String, HibernateException> checkNamedQueries(QueryEngine queryPlanCache);
/**
* Validate the named queries and throw an exception if any are broken
*/
void validateNamedQueries(QueryEngine queryEngine);
/**
* Resolve the named query with the given name.
*/
@ -82,7 +87,8 @@ public interface NamedObjectRepository {
/**
* Prepare for runtime use
*/
void prepare(SessionFactoryImplementor sessionFactory, MetadataImplementor bootMetamodel, BootstrapContext bootstrapContext);
// TODO: avoid passing in the whole SessionFactory here, it's not necessary
void prepare(SessionFactoryImplementor sessionFactory, Metadata bootMetamodel);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -14,10 +14,10 @@ import java.util.Objects;
import java.util.function.Supplier;
import org.hibernate.Incubating;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.FunctionContributor;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Dialect;
@ -373,13 +373,13 @@ public class QueryEngine {
}
}
public void prepare(
SessionFactoryImplementor sessionFactory,
MetadataImplementor bootMetamodel,
BootstrapContext bootstrapContext) {
namedObjectRepository.prepare( sessionFactory, bootMetamodel, bootstrapContext );
public void prepare(SessionFactoryImplementor sessionFactory, Metadata bootMetamodel) {
namedObjectRepository.prepare( sessionFactory, bootMetamodel );
}
public void validateNamedQueries() {
namedObjectRepository.validateNamedQueries( this );
}
public NamedObjectRepository getNamedObjectRepository() {
return namedObjectRepository;
}

View File

@ -155,12 +155,11 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
// Scoping
/**
* Obtain the {@link MetadataBuildingContext} currently scoping this
* {@code TypeConfiguration}.
* Obtain the {@link MetadataBuildingContext} currently scoping this {@code TypeConfiguration}.
*
* @apiNote This will throw an exception if the SessionFactory is not yet
* bound here. See {@link Scope} for more details regarding the stages
* a TypeConfiguration goes through
* @apiNote Throws an exception if the {@code TypeConfiguration} is no longer scoped to the
* {@link MetadataBuildingContext}. See {@link Scope} for more details regarding the
* stages a {@code TypeConfiguration} passes through.
*
* @return The {@link MetadataBuildingContext}
*/
@ -199,7 +198,7 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
}
/**
* Obtain the {@link SessionFactory} currently scoping the {@code TypeConfiguration}.
* Obtain the {@link SessionFactory} currently scoping this {@code TypeConfiguration}.
*
* @apiNote Throws an exception if the {@code TypeConfiguration} is not yet scoped to
* a factory. See {@link Scope} for more details regarding the stages a
@ -215,7 +214,7 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
}
/**
* Obtain the {@link ServiceRegistry} scoped to the {@code TypeConfiguration}.
* Obtain the {@link ServiceRegistry} scoped to this {@code TypeConfiguration}.
*
* @apiNote The current {@link Scope} will determine from where the {@link ServiceRegistry}
* is obtained.