clean up the constructor of SessionFactoryImpl

this was a really awful mess!
This commit is contained in:
Gavin 2022-12-27 16:11:02 +01:00 committed by Gavin King
parent b0479c5f29
commit c86539b6b1
3 changed files with 285 additions and 232 deletions

View File

@ -36,14 +36,12 @@ public class EventEngine {
private final CallbackRegistry callbackRegistry;
public EventEngine(
MetadataImplementor mappings,
SessionFactoryImplementor sessionFactory) {
public EventEngine(MetadataImplementor mappings, SessionFactoryImplementor sessionFactory) {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// resolve (JPA) callback handlers
this.callbackRegistry = CallbacksFactory.buildCallbackRegistry( sessionFactory.getSessionFactoryOptions(),
callbackRegistry = CallbacksFactory.buildCallbackRegistry( sessionFactory.getSessionFactoryOptions(),
sessionFactory.getServiceRegistry(), mappings.getEntityBindings() );

View File

@ -50,7 +50,6 @@ import org.hibernate.cache.cfg.spi.DomainDataRegionConfig;
import org.hibernate.cache.spi.CacheImplementor;
import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.context.internal.JTASessionContext;
import org.hibernate.context.internal.ManagedSessionContext;
import org.hibernate.context.internal.ThreadLocalSessionContext;
@ -75,7 +74,6 @@ import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.integrator.spi.IntegratorService;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.jpa.internal.ExceptionMapperLegacyJpaImpl;
import org.hibernate.jpa.internal.PersistenceUnitUtilImpl;
import org.hibernate.mapping.Collection;
@ -95,7 +93,6 @@ import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.query.BindableType;
import org.hibernate.query.QueryLogging;
import org.hibernate.query.hql.spi.SqmQueryImplementor;
import org.hibernate.query.named.NamedObjectRepository;
import org.hibernate.query.named.NamedQueryMemento;
@ -129,6 +126,12 @@ import jakarta.persistence.Query;
import jakarta.persistence.SynchronizationType;
import static java.util.Collections.unmodifiableSet;
import static org.hibernate.cfg.AvailableSettings.CREATE_EMPTY_COMPOSITES_ENABLED;
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;
/**
* Concrete implementation of the {@code SessionFactory} interface. Has the following
@ -162,7 +165,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
private final transient SessionFactoryObserverChain observer = new SessionFactoryObserverChain();
private final transient SessionFactoryOptions sessionFactoryOptions;
private final transient Map<String,Object> properties;
private final transient Map<String,Object> settings;
private final transient SessionFactoryServiceRegistry serviceRegistry;
private final transient EventEngine eventEngine;
@ -194,219 +197,93 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
private final transient SchemaManager schemaManager;
public SessionFactoryImpl(
final MetadataImplementor bootMetamodel,
SessionFactoryOptions options) {
public SessionFactoryImpl(final MetadataImplementor bootMetamodel, final SessionFactoryOptions options) {
LOG.debug( "Building session factory" );
final TypeConfiguration typeConfiguration = bootMetamodel.getTypeConfiguration();
final MetadataBuildingContext bootModelBuildingContext = typeConfiguration.getMetadataBuildingContext();
final BootstrapContext bootstrapContext = bootModelBuildingContext.getBootstrapContext();
this.sessionFactoryOptions = options;
sessionFactoryOptions = options;
this.serviceRegistry = options
.getServiceRegistry()
.getService( SessionFactoryServiceRegistryFactory.class )
.buildServiceRegistry( this, options );
serviceRegistry = getServiceRegistry( options, this );
this.eventEngine = new EventEngine( bootMetamodel, this );
eventEngine = new EventEngine( bootMetamodel, this );
bootMetamodel.initSessionFactory( this );
final CfgXmlAccessService cfgXmlAccessService = serviceRegistry.getService( CfgXmlAccessService.class );
String sfName = sessionFactoryOptions.getSessionFactoryName();
if ( cfgXmlAccessService.getAggregatedConfig() != null ) {
if ( sfName == null ) {
sfName = cfgXmlAccessService.getAggregatedConfig().getSessionFactoryName();
}
}
this.name = sfName;
this.uuid = options.getUuid();
name = getSessionFactoryName( options, serviceRegistry );
uuid = options.getUuid();
jdbcServices = serviceRegistry.getService( JdbcServices.class );
ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class );
settings = getSettings( options, serviceRegistry );
maskOutSensitiveInformation( settings );
LOG.debugf( "Instantiating SessionFactory with settings: %s", settings);
logIfEmptyCompositesEnabled( settings );
this.properties = new HashMap<>();
this.properties.putAll( configurationService.getSettings() );
if ( !properties.containsKey( AvailableSettings.JPA_VALIDATION_FACTORY )
&& !properties.containsKey( AvailableSettings.JAKARTA_VALIDATION_FACTORY ) ) {
if ( getSessionFactoryOptions().getValidatorFactoryReference() != null ) {
properties.put(
AvailableSettings.JPA_VALIDATION_FACTORY,
getSessionFactoryOptions().getValidatorFactoryReference()
);
properties.put(
AvailableSettings.JAKARTA_VALIDATION_FACTORY,
getSessionFactoryOptions().getValidatorFactoryReference()
);
}
}
sqlStringGenerationContext = createSqlStringGenerationContext( bootMetamodel, options, jdbcServices );
maskOutSensitiveInformation(this.properties);
logIfEmptyCompositesEnabled( this.properties );
cacheAccess = serviceRegistry.getService( CacheImplementor.class );
sqlStringGenerationContext = SqlStringGenerationContextImpl.fromExplicit(
jdbcServices.getJdbcEnvironment(), bootMetamodel.getDatabase(),
options.getDefaultCatalog(), options.getDefaultSchema() );
this.cacheAccess = this.serviceRegistry.getService( CacheImplementor.class );
this.jpaPersistenceUnitUtil = new PersistenceUnitUtilImpl( this );
jpaPersistenceUnitUtil = new PersistenceUnitUtilImpl( this );
for ( SessionFactoryObserver sessionFactoryObserver : options.getSessionFactoryObservers() ) {
this.observer.addObserver( sessionFactoryObserver );
observer.addObserver( sessionFactoryObserver );
}
this.filters = new HashMap<>();
this.filters.putAll( bootMetamodel.getFilterDefinitions() );
filters = new HashMap<>( bootMetamodel.getFilterDefinitions() );
LOG.debugf( "Session factory constructed with filter configurations : %s", filters );
LOG.debugf( "Instantiating session factory with properties: %s", properties );
class IntegratorObserver implements SessionFactoryObserver {
private final ArrayList<Integrator> integrators = new ArrayList<>();
entityNameResolver = new CoordinatingEntityNameResolver( this, getInterceptor() );
schemaManager = new SchemaManagerImpl( this, bootMetamodel );
@Override
public void sessionFactoryCreated(SessionFactory factory) {
}
@Override
public void sessionFactoryClosed(SessionFactory factory) {
for ( Integrator integrator : integrators ) {
integrator.disintegrate( SessionFactoryImpl.this, SessionFactoryImpl.this.serviceRegistry );
}
integrators.clear();
}
}
final IntegratorObserver integratorObserver = new IntegratorObserver();
this.observer.addObserver( integratorObserver );
observer.addObserver( integratorObserver );
try {
for ( Integrator integrator : serviceRegistry.getService( IntegratorService.class ).getIntegrators() ) {
integrator.integrate( bootMetamodel, bootstrapContext, this );
integratorObserver.integrators.add( integrator );
}
//Generators:
this.identifierGenerators = new HashMap<>();
bootMetamodel.getEntityBindings().stream().filter( model -> !model.isInherited() ).forEach( model -> {
final Generator generator = model.getIdentifier().createGenerator(
bootstrapContext.getIdentifierGeneratorFactory(),
jdbcServices.getJdbcEnvironment().getDialect(),
(RootClass) model
);
if ( generator instanceof IdentifierGenerator ) {
( (IdentifierGenerator) generator ).initialize( sqlStringGenerationContext );
}
identifierGenerators.put( model.getEntityName(), generator );
} );
integrate( bootMetamodel, bootstrapContext, integratorObserver );
identifierGenerators = createGenerators( jdbcServices, sqlStringGenerationContext, bootMetamodel, bootstrapContext );
bootMetamodel.orderColumns( false );
bootMetamodel.validate();
LOG.debug( "Instantiated session factory" );
primeSecondLevelCacheRegions( bootMetamodel );
this.queryEngine = QueryEngine.from( this, bootMetamodel );
queryEngine = QueryEngine.from( this, bootMetamodel );
final RuntimeMetamodelsImpl runtimeMetamodels = new RuntimeMetamodelsImpl();
this.runtimeMetamodels = runtimeMetamodels;
runtimeMetamodels.finishInitialization(
bootMetamodel,
bootstrapContext,
this
);
this.queryEngine.prepare( this, bootMetamodel, bootstrapContext );
final RuntimeMetamodelsImpl runtimeMetamodelsImpl = new RuntimeMetamodelsImpl();
runtimeMetamodels = runtimeMetamodelsImpl;
runtimeMetamodelsImpl.finishInitialization( bootMetamodel, bootstrapContext, this );
queryEngine.prepare( this, bootMetamodel, bootstrapContext );
if ( options.isNamedQueryStartupCheckingEnabled() ) {
final Map<String, HibernateException> errors = queryEngine.getNamedObjectRepository().checkNamedQueries( queryEngine );
if ( !errors.isEmpty() ) {
StringBuilder failingQueries = new StringBuilder( "Errors in named queries: " );
String sep = "";
for ( Map.Entry<String, HibernateException> entry : errors.entrySet() ) {
QueryLogging.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;
}
checkNamedQueries( queryEngine );
}
SchemaManagementToolCoordinator.process(
bootMetamodel,
serviceRegistry,
properties,
action -> SessionFactoryImpl.this.delayedDropAction = action
);
exportSchema( bootMetamodel );
currentSessionContext = buildCurrentSessionContext();
// this needs to happen after persisters are all ready to go...
this.fetchProfiles = new HashMap<>();
for ( org.hibernate.mapping.FetchProfile mappingProfile : bootMetamodel.getFetchProfiles() ) {
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 = this.runtimeMetamodels.getImportedName( mappingFetch.getEntity() );
final EntityPersister owner = entityName == null
? null
: this.runtimeMetamodels.getMappingMetamodel().getEntityDescriptor( entityName );
if ( owner == null ) {
throw new HibernateException(
"Unable to resolve entity reference [" + mappingFetch.getEntity()
+ "] in fetch profile [" + fetchProfile.getName() + "]"
);
}
fetchProfiles = getFetchProfiles( bootMetamodel, runtimeMetamodelsImpl );
// validate the specified association fetch
Type associationType = owner.getPropertyType( mappingFetch.getAssociation() );
if ( associationType == null || !associationType.isAssociationType() ) {
throw new HibernateException( "Fetch profile [" + fetchProfile.getName() + "] specified an invalid association" );
}
defaultSessionOpenOptions = createDefaultSessionOpenOptionsIfPossible();
temporarySessionOpenOptions = defaultSessionOpenOptions == null ? null : buildTemporarySessionOpenOptions();
defaultStatelessOptions = defaultSessionOpenOptions == null ? null : withStatelessOptions();
fastSessionServices = new FastSessionServices( this );
wrapperOptions = new SessionFactoryBasedWrapperOptions( this );
// resolve the style
final Fetch.Style fetchStyle = Fetch.Style.parse( mappingFetch.getStyle() );
observer.sessionFactoryCreated( this );
// then construct the fetch instance...
fetchProfile.addFetch( new Association( owner, mappingFetch.getAssociation() ), fetchStyle );
((Loadable) owner).registerAffectingFetchProfile( fetchProfile.getName() );
}
fetchProfiles.put( fetchProfile.getName(), fetchProfile );
}
addToRegistry();
this.defaultSessionOpenOptions = createDefaultSessionOpenOptionsIfPossible();
this.temporarySessionOpenOptions = this.defaultSessionOpenOptions == null ? null : buildTemporarySessionOpenOptions();
this.defaultStatelessOptions = this.defaultSessionOpenOptions == null ? null : withStatelessOptions();
this.fastSessionServices = new FastSessionServices( this );
this.wrapperOptions = new SessionFactoryBasedWrapperOptions( this );
this.observer.sessionFactoryCreated( this );
SessionFactoryRegistry.INSTANCE.addSessionFactory(
getUuid(),
name,
sessionFactoryOptions.isSessionFactoryNameAlsoJndiName(),
this,
serviceRegistry.getService( JndiService.class )
);
//As last operation, delete all caches from ReflectionManager
//(not modelled as a listener as we want this to be last)
// As last operation, delete all caches from ReflectionManager
// (not modelled as a listener as we want this to be last)
bootstrapContext.getReflectionManager().reset();
this.entityNameResolver = new CoordinatingEntityNameResolver( this, getInterceptor() );
}
catch (Exception e) {
for ( Integrator integrator : serviceRegistry.getService( IntegratorService.class ).getIntegrators() ) {
integrator.disintegrate( this, serviceRegistry );
integratorObserver.integrators.remove( integrator );
serviceRegistry.close();
}
catch ( Exception e ) {
disintegrate( integratorObserver );
try {
close();
@ -417,7 +294,184 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
throw e;
}
this.schemaManager = new SchemaManagerImpl( this, bootMetamodel );
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,
MetadataImplementor bootMetamodel,
BootstrapContext bootstrapContext) {
final Map<String, Generator> generators = new HashMap<>();
bootMetamodel.getEntityBindings().stream()
.filter( model -> !model.isInherited() )
.forEach( model -> {
final Generator generator = model.getIdentifier().createGenerator(
bootstrapContext.getIdentifierGeneratorFactory(),
jdbcServices.getJdbcEnvironment().getDialect(),
(RootClass) model
);
if ( generator instanceof IdentifierGenerator ) {
( (IdentifierGenerator) generator ).initialize( sqlStringGenerationContext );
}
generators.put( model.getEntityName(), generator );
} );
return generators;
}
private SqlStringGenerationContext createSqlStringGenerationContext(
MetadataImplementor bootMetamodel,
SessionFactoryOptions options,
JdbcServices jdbcServices) {
return SqlStringGenerationContextImpl.fromExplicit(
jdbcServices.getJdbcEnvironment(),
bootMetamodel.getDatabase(),
options.getDefaultCatalog(),
options.getDefaultSchema()
);
}
private static SessionFactoryServiceRegistry getServiceRegistry(
SessionFactoryOptions options,
SessionFactoryImplementor self) {
return options
.getServiceRegistry()
.getService( SessionFactoryServiceRegistryFactory.class )
// it is not great how we pass in an instance to
// an incompletely-initialized instance here:
.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<>();
@Override
public void sessionFactoryCreated(SessionFactory factory) {
}
@Override
public void sessionFactoryClosed(SessionFactory factory) {
for ( Integrator integrator : integrators ) {
integrator.disintegrate( SessionFactoryImpl.this, SessionFactoryImpl.this.serviceRegistry );
}
integrators.clear();
}
}
private void integrate(MetadataImplementor bootMetamodel, BootstrapContext bootstrapContext, IntegratorObserver integratorObserver) {
for ( Integrator integrator : serviceRegistry.getService( IntegratorService.class ).getIntegrators() ) {
integrator.integrate(bootMetamodel, bootstrapContext, this );
integratorObserver.integrators.add( integrator );
}
}
private void disintegrate(IntegratorObserver integratorObserver) {
for ( Integrator integrator : serviceRegistry.getService( IntegratorService.class ).getIntegrators() ) {
integrator.disintegrate( this, serviceRegistry );
integratorObserver.integrators.remove( integrator );
serviceRegistry.close();
}
}
private static Map<String, FetchProfile> getFetchProfiles(
MetadataImplementor bootMetamodel,
RuntimeMetamodelsImpl runtimeMetamodels) {
final Map<String, FetchProfile> fetchProfiles = new HashMap<>();
for ( org.hibernate.mapping.FetchProfile mappingProfile : bootMetamodel.getFetchProfiles() ) {
final FetchProfile fetchProfile = createFetchProfile( runtimeMetamodels, mappingProfile );
fetchProfiles.put( fetchProfile.getName(), fetchProfile );
}
return fetchProfiles;
}
private static FetchProfile createFetchProfile(
RuntimeMetamodelsImpl runtimeMetamodels,
org.hibernate.mapping.FetchProfile mappingProfile) {
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() + "]"
);
}
// validate the specified association fetch
final Type associationType = owner.getPropertyType( mappingFetch.getAssociation() );
if ( associationType == null || !associationType.isAssociationType() ) {
throw new HibernateException( "Fetch profile [" + fetchProfile.getName() + "] specified an invalid association" );
}
// resolve the style
final Fetch.Style fetchStyle = Fetch.Style.parse( mappingFetch.getStyle() );
// then construct the fetch instance...
fetchProfile.addFetch( new Association( owner, mappingFetch.getAssociation() ), fetchStyle );
((Loadable) owner).registerAffectingFetchProfile( fetchProfile.getName() );
}
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 = ", ";
}
final HibernateException exception = new HibernateException( failingQueries.toString() );
errors.values().forEach( exception::addSuppressed );
throw exception;
}
}
private static Map<String, Object> getSettings(SessionFactoryOptions options, SessionFactoryServiceRegistry serviceRegistry) {
final Map<String, Object> settings = serviceRegistry.getService( ConfigurationService.class ).getSettings();
final Map<String,Object> result = new HashMap<>( settings );
if ( !settings.containsKey( JPA_VALIDATION_FACTORY ) && !settings.containsKey( JAKARTA_VALIDATION_FACTORY ) ) {
final Object reference = options.getValidatorFactoryReference();
if ( reference != null ) {
result.put( JPA_VALIDATION_FACTORY, reference );
result.put( JAKARTA_VALIDATION_FACTORY, reference );
}
}
return result;
}
private static String getSessionFactoryName(SessionFactoryOptions options, SessionFactoryServiceRegistry serviceRegistry) {
final CfgXmlAccessService cfgXmlAccessService = serviceRegistry.getService( CfgXmlAccessService.class );
final String sessionFactoryName = options.getSessionFactoryName();
return sessionFactoryName == null && cfgXmlAccessService.getAggregatedConfig() != null
? cfgXmlAccessService.getAggregatedConfig().getSessionFactoryName()
: sessionFactoryName;
}
private SessionBuilderImpl createDefaultSessionOpenOptionsIfPossible() {
@ -494,23 +548,22 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
public SessionImplementor openSession() throws HibernateException {
//The defaultSessionOpenOptions can't be used in some cases; for example when using a TenantIdentifierResolver.
if ( this.defaultSessionOpenOptions != null ) {
return this.defaultSessionOpenOptions.openSession();
if ( defaultSessionOpenOptions != null ) {
return defaultSessionOpenOptions.openSession();
}
else {
return this.withOptions().openSession();
return withOptions().openSession();
}
}
@Override
public SessionImpl openTemporarySession() throws HibernateException {
//The temporarySessionOpenOptions can't be used in some cases; for example when using a TenantIdentifierResolver.
if ( this.temporarySessionOpenOptions != null ) {
return this.temporarySessionOpenOptions.openSession();
if ( temporarySessionOpenOptions != null ) {
return temporarySessionOpenOptions.openSession();
}
else {
return buildTemporarySessionOpenOptions()
.openSession();
return buildTemporarySessionOpenOptions().openSession();
}
}
@ -552,7 +605,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
@Override
public Map<String, Object> getProperties() {
validateNotClosed();
return properties;
return settings;
}
protected void validateNotClosed() {
@ -989,24 +1042,29 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
try {
return serviceRegistry.getService( JtaPlatform.class ).retrieveTransactionManager() != null;
}
catch (Exception e) {
catch ( Exception e ) {
return false;
}
}
private CurrentSessionContext buildCurrentSessionContext() {
String impl = (String) properties.get( Environment.CURRENT_SESSION_CONTEXT_CLASS );
final String sessionContextType = (String) settings.get( CURRENT_SESSION_CONTEXT_CLASS );
// for backward-compatibility
if ( impl == null ) {
if ( sessionContextType == null ) {
if ( canAccessTransactionManager() ) {
impl = "jta";
return createSessionContext( "jta" );
}
else {
return null;
}
}
else {
return createSessionContext( sessionContextType );
}
}
switch (impl) {
private CurrentSessionContext createSessionContext(String sessionContextType) {
switch ( sessionContextType ) {
case "jta":
// if ( ! transactionFactory().compatibleWithJtaSynchronization() ) {
// LOG.autoFlushWillNotWork();
@ -1018,13 +1076,14 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
return new ManagedSessionContext(this);
default:
try {
Class<?> implClass = serviceRegistry.getService(ClassLoaderService.class).classForName(impl);
return (CurrentSessionContext)
implClass.getConstructor( new Class[]{SessionFactoryImplementor.class} )
.newInstance(this);
serviceRegistry.getService( ClassLoaderService.class )
.classForName( sessionContextType )
.getConstructor( new Class[]{ SessionFactoryImplementor.class } )
.newInstance( this );
}
catch (Throwable t) {
LOG.unableToConstructCurrentSessionContext(impl, t);
catch ( Throwable t ) {
LOG.unableToConstructCurrentSessionContext( sessionContextType, t );
return null;
}
}
@ -1067,25 +1126,20 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
return null;
}
Class<?> clazz;
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( bindValue );
if ( lazyInitializer != null ) {
clazz = lazyInitializer.getPersistentClass();
}
else {
clazz = bindValue.getClass();
}
final Class<?> clazz = lazyInitializer != null ? lazyInitializer.getPersistentClass() : bindValue.getClass();
// Resolve superclass bindable type if necessary, as we don't register types for e.g. Inet4Address
Class<?> c = clazz;
do {
BindableType<?> type = resolveParameterBindType( c );
final BindableType<?> type = resolveParameterBindType( c );
if ( type != null ) {
//noinspection unchecked
return (BindableType<? extends T>) type;
}
c = c.getSuperclass();
} while ( c != Object.class );
}
while ( c != Object.class );
if ( !clazz.isEnum() && Serializable.class.isAssignableFrom( clazz ) ) {
//noinspection unchecked
return (BindableType<? extends T>) resolveParameterBindType( Serializable.class );
@ -1560,12 +1614,8 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
}
private void logIfEmptyCompositesEnabled(Map<String, Object> props ) {
final boolean isEmptyCompositesEnabled = ConfigurationHelper.getBoolean(
AvailableSettings.CREATE_EMPTY_COMPOSITES_ENABLED,
props,
false
);
final boolean isEmptyCompositesEnabled =
getBoolean( CREATE_EMPTY_COMPOSITES_ENABLED, props, false );
if ( isEmptyCompositesEnabled ) {
LOG.emptyCompositesEnabled();
}

View File

@ -113,7 +113,6 @@ import org.hibernate.jpa.internal.LegacySpecHelper;
import org.hibernate.jpa.internal.util.ConfigurationHelper;
import org.hibernate.jpa.internal.util.FlushModeTypeHelper;
import org.hibernate.jpa.internal.util.LockModeTypeHelper;
import org.hibernate.jpa.internal.util.LockOptionsHelper;
import org.hibernate.loader.internal.IdentifierLoadAccessImpl;
import org.hibernate.loader.internal.LoadAccessContext;
import org.hibernate.loader.internal.NaturalIdLoadAccessImpl;
@ -150,6 +149,7 @@ import jakarta.persistence.TransactionRequiredException;
import jakarta.persistence.metamodel.Metamodel;
import static java.lang.Boolean.parseBoolean;
import static java.lang.System.currentTimeMillis;
import static java.util.Collections.unmodifiableMap;
import static org.hibernate.CacheMode.fromJpaModes;
import static org.hibernate.cfg.AvailableSettings.*;
@ -159,6 +159,7 @@ import static org.hibernate.jpa.LegacySpecHints.HINT_JAVAEE_QUERY_TIMEOUT;
import static org.hibernate.jpa.SpecHints.HINT_SPEC_LOCK_TIMEOUT;
import static org.hibernate.jpa.SpecHints.HINT_SPEC_QUERY_TIMEOUT;
import static org.hibernate.jpa.internal.util.CacheModeHelper.interpretCacheMode;
import static org.hibernate.jpa.internal.util.LockOptionsHelper.applyPropertiesToLockOptions;
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
/**
@ -207,11 +208,11 @@ public class SessionImpl
public SessionImpl(SessionFactoryImpl factory, SessionCreationOptions options) {
super( factory, options );
this.persistenceContext = createPersistenceContext();
this.actionQueue = createActionQueue();
persistenceContext = createPersistenceContext();
actionQueue = createActionQueue();
this.autoClear = options.shouldAutoClear();
this.autoClose = options.shouldAutoClose();
autoClear = options.shouldAutoClear();
autoClose = options.shouldAutoClose();
if ( options instanceof SharedSessionCreationOptions ) {
final SharedSessionCreationOptions sharedOptions = (SharedSessionCreationOptions) options;
@ -232,9 +233,9 @@ public class SessionImpl
statistics.openSession();
}
if ( this.properties != null ) {
if ( properties != null ) {
//There might be custom properties for this session that affect the LockOptions state
LockOptionsHelper.applyPropertiesToLockOptions( this.properties, this::getLockOptionsForWrite );
applyPropertiesToLockOptions( properties, this::getLockOptionsForWrite );
}
setCacheMode( fastSessionServices.initialSessionCacheMode );
@ -243,23 +244,31 @@ public class SessionImpl
// do not override explicitly set flush mode ( SessionBuilder#flushMode() )
if ( getHibernateFlushMode() == null ) {
final FlushMode initialMode = this.properties == null
? fastSessionServices.initialSessionFlushMode
: ConfigurationHelper.getFlushMode(
getSessionProperty(FLUSH_MODE),
FlushMode.AUTO
);
setHibernateFlushMode( initialMode );
setHibernateFlushMode( getInitialFlushMode() );
}
setUpMultitenancy( factory );
if ( log.isTraceEnabled() ) {
log.tracef( "Opened Session [%s] at timestamp: %s", getSessionIdentifier(), currentTimeMillis() );
}
}
private FlushMode getInitialFlushMode() {
return properties == null
? fastSessionServices.initialSessionFlushMode
: ConfigurationHelper.getFlushMode( getSessionProperty( FLUSH_MODE ), FlushMode.AUTO );
}
private void setUpMultitenancy(SessionFactoryImplementor factory) {
if ( factory.getDefinedFilterNames().contains( TenantIdBinder.FILTER_NAME ) ) {
String tenantIdentifier = getTenantIdentifier();
final String tenantIdentifier = getTenantIdentifier();
if ( tenantIdentifier == null ) {
throw new HibernateException( "SessionFactory configured for multi-tenancy, but no tenant identifier specified" );
}
else {
CurrentTenantIdentifierResolver resolver = factory.getCurrentTenantIdentifierResolver();
if ( resolver==null || !resolver.isRoot(tenantIdentifier) ) {
final CurrentTenantIdentifierResolver resolver = factory.getCurrentTenantIdentifierResolver();
if ( resolver==null || !resolver.isRoot( tenantIdentifier ) ) {
// turn on the filter, unless this is the "root" tenant with access to all partitions
loadQueryInfluencers
.enableFilter( TenantIdBinder.FILTER_NAME )
@ -267,10 +276,6 @@ public class SessionImpl
}
}
}
if ( log.isTraceEnabled() ) {
log.tracef( "Opened Session [%s] at timestamp: %s", getSessionIdentifier(), System.currentTimeMillis() );
}
}
protected StatefulPersistenceContext createPersistenceContext() {
@ -2572,7 +2577,7 @@ public class SessionImpl
}
lockOptions.setLockMode( LockModeTypeHelper.getLockMode( lockModeType ) );
if ( properties != null ) {
LockOptionsHelper.applyPropertiesToLockOptions( properties, () -> lockOptions );
applyPropertiesToLockOptions( properties, () -> lockOptions );
}
return lockOptions;
}
@ -2637,13 +2642,13 @@ public class SessionImpl
case JAKARTA_LOCK_SCOPE:
properties.put( JPA_LOCK_SCOPE, value);
properties.put( JAKARTA_LOCK_SCOPE, value);
LockOptionsHelper.applyPropertiesToLockOptions( properties, this::getLockOptionsForWrite );
applyPropertiesToLockOptions( properties, this::getLockOptionsForWrite );
break;
case JPA_LOCK_TIMEOUT:
case JAKARTA_LOCK_TIMEOUT:
properties.put( JPA_LOCK_TIMEOUT, value );
properties.put( JAKARTA_LOCK_TIMEOUT, value );
LockOptionsHelper.applyPropertiesToLockOptions( properties, this::getLockOptionsForWrite );
applyPropertiesToLockOptions( properties, this::getLockOptionsForWrite );
break;
case JPA_SHARED_CACHE_RETRIEVE_MODE:
case JAKARTA_SHARED_CACHE_RETRIEVE_MODE: