HHH-12444 - Introduce BootstrapContext

HHH-12443 - Introduce TypeConfiguration
This commit is contained in:
Andrea Boriero 2018-03-14 18:59:15 +00:00 committed by Steve Ebersole
parent 9229514ed4
commit 11462e7860
19 changed files with 395 additions and 83 deletions

View File

@ -36,6 +36,7 @@ import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.type.spi.TypeConfiguration;
import org.jboss.jandex.IndexView;
import org.jboss.logging.Logger;
@ -50,6 +51,8 @@ public class BootstrapContextImpl implements BootstrapContext {
private final StandardServiceRegistry serviceRegistry;
private final TypeConfiguration typeConfiguration;
private final ClassLoaderAccessImpl classLoaderAccess;
private final JavaReflectionManager hcannReflectionManager;
@ -102,6 +105,7 @@ public class BootstrapContextImpl implements BootstrapContext {
ArchiveDescriptorFactory.class,
configService.getSettings().get( AvailableSettings.SCANNER_ARCHIVE_INTERPRETER )
);
this.typeConfiguration = new TypeConfiguration();
}
@Override
@ -109,6 +113,11 @@ public class BootstrapContextImpl implements BootstrapContext {
return serviceRegistry;
}
@Override
public TypeConfiguration getTypeConfiguration() {
return typeConfiguration;
}
@Override
public MetadataBuildingOptions getMetadataBuildingOptions() {
return metadataBuildingOptions;

View File

@ -106,6 +106,7 @@ import org.hibernate.mapping.Table;
import org.hibernate.mapping.UniqueKey;
import org.hibernate.query.spi.NamedQueryRepository;
import org.hibernate.type.TypeResolver;
import org.hibernate.type.spi.TypeConfiguration;
/**
* The implementation of the in-flight Metadata collector contract.
@ -121,6 +122,8 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
private final BootstrapContext bootstrapContext;
private final MetadataBuildingOptions options;
private final TypeConfiguration typeConfiguration;
private final TypeResolver typeResolver;
private final AttributeConverterManager attributeConverterManager = new AttributeConverterManager();
@ -167,6 +170,16 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
private Map<Table, List<UniqueConstraintHolder>> uniqueConstraintHoldersByTable;
private Map<Table, List<JPAIndexHolder>> jpaIndexHoldersByTable;
public InFlightMetadataCollectorImpl(
BootstrapContext bootstrapContext,
MetadataBuildingOptions options) {
this( bootstrapContext, options, bootstrapContext.getTypeConfiguration().getTypeResolver() );
}
/**
* @deprecated Use {@link InFlightMetadataCollectorImpl#InFlightMetadataCollectorImpl(BootstrapContext, MetadataBuildingOptions)} instead.
*/
@Deprecated
public InFlightMetadataCollectorImpl(
BootstrapContext bootstrapContext,
MetadataBuildingOptions options,
@ -174,6 +187,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
this.bootstrapContext = bootstrapContext;
this.uuid = UUID.randomUUID();
this.options = options;
this.typeConfiguration = bootstrapContext.getTypeConfiguration();
this.typeResolver = typeResolver;
this.identifierGeneratorFactory = options.getServiceRegistry().getService( MutableIdentifierGeneratorFactory.class );
@ -205,6 +219,11 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
return bootstrapContext;
}
@Override
public TypeConfiguration getTypeConfiguration() {
return typeConfiguration;
}
@Override
public TypeResolver getTypeResolver() {
return typeResolver;
@ -2231,7 +2250,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
return new MetadataImpl(
uuid,
options,
typeResolver,
typeConfiguration,
identifierGeneratorFactory,
entityBindingMap,
mappedSuperClasses,

View File

@ -50,6 +50,7 @@ import org.hibernate.mapping.Table;
import org.hibernate.procedure.ProcedureCallMemento;
import org.hibernate.query.spi.NamedQueryRepository;
import org.hibernate.type.TypeResolver;
import org.hibernate.type.spi.TypeConfiguration;
/**
* Container for configuration data collected during binding the metamodel.
@ -61,8 +62,8 @@ import org.hibernate.type.TypeResolver;
public class MetadataImpl implements MetadataImplementor, Serializable {
private final UUID uuid;
private final MetadataBuildingOptions metadataBuildingOptions;
private final BootstrapContext bootstrapContext;
private final TypeResolver typeResolver;
private final IdentifierGeneratorFactory identifierGeneratorFactory;
private final Map<String,PersistentClass> entityBindingMap;
@ -81,12 +82,10 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
private final Map<String, SQLFunction> sqlFunctionMap;
private final java.util.Collection<DomainDataRegionConfigImpl.Builder> cacheRegionConfigBuilders;
private final Database database;
private final BootstrapContext bootstrapContext;
public MetadataImpl(
MetadataImpl(
UUID uuid,
MetadataBuildingOptions metadataBuildingOptions,
TypeResolver typeResolver,
MutableIdentifierGeneratorFactory identifierGeneratorFactory,
Map<String, PersistentClass> entityBindingMap,
Map<Class, MappedSuperclass> mappedSuperclassMap,
@ -107,7 +106,6 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
BootstrapContext bootstrapContext) {
this.uuid = uuid;
this.metadataBuildingOptions = metadataBuildingOptions;
this.typeResolver = typeResolver;
this.identifierGeneratorFactory = identifierGeneratorFactory;
this.entityBindingMap = entityBindingMap;
this.mappedSuperclassMap = mappedSuperclassMap;
@ -133,9 +131,14 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
return metadataBuildingOptions;
}
@Override
public TypeConfiguration getTypeConfiguration() {
return bootstrapContext.getTypeConfiguration();
}
@Override
public TypeResolver getTypeResolver() {
return typeResolver;
return bootstrapContext.getTypeConfiguration().getTypeResolver();
}
@Override
@ -318,7 +321,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
}
public Map<String, ProcedureCallMemento> buildProcedureCallMementos(SessionFactoryImpl sessionFactory) {
private Map<String, ProcedureCallMemento> buildProcedureCallMementos(SessionFactoryImpl sessionFactory) {
final Map<String, ProcedureCallMemento> rtn = new HashMap<>();
if ( namedProcedureCallMap != null ) {
for ( NamedProcedureCallDefinition procedureCallDefinition : namedProcedureCallMap.values() ) {

View File

@ -40,6 +40,7 @@ import org.hibernate.type.BasicType;
import org.hibernate.type.BasicTypeRegistry;
import org.hibernate.type.TypeFactory;
import org.hibernate.type.TypeResolver;
import org.hibernate.type.spi.TypeConfiguration;
import org.hibernate.usertype.CompositeUserType;
import org.hibernate.usertype.UserType;
@ -115,14 +116,13 @@ public class MetadataBuildingProcess {
final ManagedResources managedResources,
final BootstrapContext bootstrapContext,
final MetadataBuildingOptions options) {
final BasicTypeRegistry basicTypeRegistry = handleTypes( bootstrapContext, options );
final InFlightMetadataCollectorImpl metadataCollector = new InFlightMetadataCollectorImpl(
bootstrapContext,
options,
new TypeResolver( basicTypeRegistry, new TypeFactory() )
options
);
handleTypes( bootstrapContext, options );
final ClassLoaderService classLoaderService = options.getServiceRegistry().getService( ClassLoaderService.class );
final MetadataBuildingContextRootImpl rootMetadataBuildingContext = new MetadataBuildingContextRootImpl(
@ -137,6 +137,9 @@ public class MetadataBuildingProcess {
);
}
bootstrapContext.getTypeConfiguration().scope( rootMetadataBuildingContext );
final IndexView jandexView = bootstrapContext.getJandexView();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -266,7 +269,7 @@ public class MetadataBuildingProcess {
processor.processFilterDefinitions();
processor.processFetchProfiles();
final Set<String> processedEntityNames = new HashSet<String>();
final Set<String> processedEntityNames = new HashSet<>();
processor.prepareForEntityHierarchyProcessing();
processor.processEntityHierarchies( processedEntityNames );
processor.postProcessEntityHierarchies();
@ -311,6 +314,7 @@ public class MetadataBuildingProcess {
return metadataCollector.buildMetadataInstance( rootMetadataBuildingContext );
}
// todo (7.0) : buildJandexInitializer
// private static JandexInitManager buildJandexInitializer(
// MetadataBuildingOptions options,
// ClassLoaderAccess classLoaderAccess) {
@ -323,33 +327,34 @@ public class MetadataBuildingProcess {
// return new JandexInitManager( options.getJandexView(), classLoaderAccess, autoIndexMembers );
// }
private static BasicTypeRegistry handleTypes(BootstrapContext bootstrapContext, MetadataBuildingOptions options) {
private static void handleTypes(BootstrapContext bootstrapContext, MetadataBuildingOptions options) {
final ClassLoaderService classLoaderService = options.getServiceRegistry().getService( ClassLoaderService.class );
// ultimately this needs to change a little bit to account for HHH-7792
final BasicTypeRegistry basicTypeRegistry = new BasicTypeRegistry();
final TypeContributions typeContributions = new TypeContributions() {
@Override
public void contributeType(org.hibernate.type.BasicType type) {
basicTypeRegistry.register( type );
getBasicTypeRegistry().register( type );
}
@Override
public void contributeType(BasicType type, String... keys) {
basicTypeRegistry.register( type, keys );
getBasicTypeRegistry().register( type, keys );
}
@Override
public void contributeType(UserType type, String[] keys) {
basicTypeRegistry.register( type, keys );
getBasicTypeRegistry().register( type, keys );
}
@Override
public void contributeType(CompositeUserType type, String[] keys) {
basicTypeRegistry.register( type, keys );
getBasicTypeRegistry().register( type, keys );
}
final BasicTypeRegistry getBasicTypeRegistry() {
return bootstrapContext.getTypeConfiguration().getBasicTypeRegistry();
}
};
// add Dialect contributed types
@ -363,13 +368,13 @@ public class MetadataBuildingProcess {
// add explicit application registered types
for ( BasicTypeRegistration basicTypeRegistration : options.getBasicTypeRegistrations() ) {
basicTypeRegistry.register(
bootstrapContext.getTypeConfiguration().getBasicTypeRegistry().register(
basicTypeRegistration.getBasicType(),
basicTypeRegistration.getRegistrationKeys()
);
}
return basicTypeRegistry;
}
}

View File

@ -34,6 +34,7 @@ import org.hibernate.mapping.Table;
import org.hibernate.query.spi.NamedQueryRepository;
import org.hibernate.type.Type;
import org.hibernate.type.TypeResolver;
import org.hibernate.type.spi.TypeConfiguration;
/**
* Convenience base class for custom implementors of {@link MetadataImplementor} using delegation.
@ -208,6 +209,11 @@ public abstract class AbstractDelegatingMetadata implements MetadataImplementor
return delegate.getMetadataBuildingOptions();
}
@Override
public TypeConfiguration getTypeConfiguration() {
return delegate.getTypeConfiguration();
}
@Override
public TypeResolver getTypeResolver() {
return delegate.getTypeResolver();

View File

@ -20,6 +20,7 @@ import org.hibernate.boot.internal.ClassmateContext;
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.type.spi.TypeConfiguration;
import org.jboss.jandex.IndexView;
@ -33,6 +34,7 @@ import org.jboss.jandex.IndexView;
public interface BootstrapContext {
StandardServiceRegistry getServiceRegistry();
TypeConfiguration getTypeConfiguration();
MetadataBuildingOptions getMetadataBuildingOptions();

View File

@ -48,7 +48,6 @@ import org.hibernate.mapping.Join;
import org.hibernate.mapping.MappedSuperclass;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Table;
import org.hibernate.type.TypeResolver;
/**
* An in-flight representation of Metadata while Metadata is being built.
@ -207,10 +206,6 @@ public interface InFlightMetadataCollector extends Mapping, MetadataImplementor
void addFetchProfile(FetchProfile profile);
TypeResolver getTypeResolver();
Database getDatabase();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// make sure these are account for better in metamodel

View File

@ -16,7 +16,9 @@ import org.hibernate.engine.spi.Mapping;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.mapping.MappedSuperclass;
import org.hibernate.query.spi.NamedQueryRepository;
import org.hibernate.type.Type;
import org.hibernate.type.TypeResolver;
import org.hibernate.type.spi.TypeConfiguration;
/**
* The SPI-level Metadata contract.
@ -35,6 +37,16 @@ public interface MetadataImplementor extends Metadata, Mapping {
*/
MetadataBuildingOptions getMetadataBuildingOptions();
TypeConfiguration getTypeConfiguration();
/**
* Retrieve the {@link Type} resolver associated with this factory.
*
* @return The type resolver
*
* @deprecated (since 5.3) No replacement, access to and handling of Types will be much different in 6.0
*/
@Deprecated
TypeResolver getTypeResolver();
NamedQueryRepository buildNamedQueryRepository(SessionFactoryImpl sessionFactory);

View File

@ -125,6 +125,7 @@ import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator;
import org.hibernate.type.SerializableType;
import org.hibernate.type.Type;
import org.hibernate.type.TypeResolver;
import org.hibernate.type.spi.TypeConfiguration;
import org.jboss.logging.Logger;
@ -244,8 +245,9 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
for ( SessionFactoryObserver sessionFactoryObserver : options.getSessionFactoryObservers() ) {
this.observer.addObserver( sessionFactoryObserver );
}
this.typeResolver = metadata.getTypeResolver().scope( this );
TypeConfiguration typeConfiguration = metadata.getTypeConfiguration();
typeConfiguration.scope( this );
this.typeResolver = typeConfiguration.getTypeResolver();
this.typeHelper = new TypeLocatorImpl( typeResolver );
this.filters = new HashMap<>();

View File

@ -387,7 +387,7 @@ public abstract class Collection implements Fetchable, Value, Filterable {
return getDefaultCollectionType();
}
else {
return getMetadata().getTypeResolver()
return getMetadata().getTypeConfiguration().getTypeResolver()
.getTypeFactory()
.customCollection( typeName, typeParameters, role, referencedPropertyName );
}

View File

@ -214,7 +214,7 @@ public class Component extends SimpleValue implements MetaAttributable {
this,
getMetadata().getMetadataBuildingOptions()
);
final TypeFactory factory = getMetadata().getTypeResolver().getTypeFactory();
final TypeFactory factory = getMetadata().getTypeConfiguration().getTypeResolver().getTypeFactory();
return isEmbedded() ? factory.embeddedComponent( metamodel ) : factory.component( metamodel );
}

View File

@ -466,7 +466,7 @@ public class SimpleValue implements KeyValue {
createParameterImpl();
}
Type result = getMetadata().getTypeResolver().heuristicType( typeName, typeParameters );
Type result = getMetadata().getTypeConfiguration().getTypeResolver().heuristicType( typeName, typeParameters );
// if this is a byte[] version/timestamp, then we need to use RowVersionType
// instead of BinaryType (HHH-10413)
if ( isVersion && BinaryType.class.isInstance( result ) ) {

View File

@ -13,6 +13,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.hibernate.HibernateException;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.type.spi.TypeConfiguration;
import org.hibernate.usertype.CompositeUserType;
import org.hibernate.usertype.UserType;
@ -25,8 +26,14 @@ public class BasicTypeRegistry implements Serializable {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( BasicTypeRegistry.class );
// TODO : analyze these sizing params; unfortunately this seems to be the only way to give a "concurrencyLevel"
private Map<String, BasicType> registry = new ConcurrentHashMap<String, BasicType>( 100, .75f, 1 );
private Map<String, BasicType> registry = new ConcurrentHashMap<>( 100, .75f, 1 );
private boolean locked;
private TypeConfiguration typeConfiguration;
public BasicTypeRegistry(TypeConfiguration typeConfiguration){
this();
this.typeConfiguration = typeConfiguration;
}
public BasicTypeRegistry() {
register( BooleanType.INSTANCE );

View File

@ -10,15 +10,13 @@ import java.io.Serializable;
import java.util.Comparator;
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.boot.cfgxml.spi.CfgXmlAccessService;
import org.hibernate.classic.Lifecycle;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.SessionFactoryRegistry;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.tuple.component.ComponentMetamodel;
import org.hibernate.type.spi.TypeConfiguration;
import org.hibernate.usertype.CompositeUserType;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType;
@ -41,47 +39,24 @@ public final class TypeFactory implements Serializable {
private final TypeScopeImpl typeScope = new TypeScopeImpl();
public static interface TypeScope extends Serializable {
public SessionFactoryImplementor resolveFactory();
public interface TypeScope extends Serializable {
SessionFactoryImplementor resolveFactory();
}
private final TypeConfiguration typeConfiguration;
public TypeFactory(TypeConfiguration typeConfiguration) {
this.typeConfiguration = typeConfiguration;
}
private static class TypeScopeImpl implements TypeFactory.TypeScope {
private transient SessionFactoryImplementor factory;
private String sessionFactoryName;
private String sessionFactoryUuid;
public void injectSessionFactory(SessionFactoryImplementor factory) {
if ( this.factory != null ) {
LOG.scopingTypesToSessionFactoryAfterAlreadyScoped( this.factory, factory );
}
else {
LOG.tracev( "Scoping types to session factory {0}", factory );
sessionFactoryUuid = factory.getUuid();
String sfName = factory.getSettings().getSessionFactoryName();
if ( sfName == null ) {
final CfgXmlAccessService cfgXmlAccessService = factory.getServiceRegistry()
.getService( CfgXmlAccessService.class );
if ( cfgXmlAccessService.getAggregatedConfig() != null ) {
sfName = cfgXmlAccessService.getAggregatedConfig().getSessionFactoryName();
}
}
sessionFactoryName = sfName;
}
this.factory = factory;
}
public SessionFactoryImplementor resolveFactory() {
if ( factory == null ) {
factory = (SessionFactoryImplementor) SessionFactoryRegistry.INSTANCE.findSessionFactory(
sessionFactoryUuid,
sessionFactoryName
);
if ( factory == null ) {
throw new HibernateException(
"Could not find a SessionFactory [uuid=" + sessionFactoryUuid + ",name=" + sessionFactoryName + "]"
);
}
}
return factory;
}
}
@ -91,7 +66,7 @@ public final class TypeFactory implements Serializable {
}
public SessionFactoryImplementor resolveSessionFactory() {
return typeScope.resolveFactory();
return typeConfiguration.getSessionFactory();
}
public Type byClass(Class clazz, Properties parameters) {

View File

@ -10,8 +10,8 @@ import java.io.Serializable;
import java.util.Properties;
import org.hibernate.MappingException;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.type.spi.TypeConfiguration;
import org.hibernate.usertype.CompositeUserType;
import org.hibernate.usertype.UserType;
@ -24,19 +24,28 @@ public class TypeResolver implements Serializable {
private final BasicTypeRegistry basicTypeRegistry;
private final TypeFactory typeFactory;
public TypeResolver() {
this( new BasicTypeRegistry(), new TypeFactory() );
}
public TypeResolver(BasicTypeRegistry basicTypeRegistry, TypeFactory typeFactory) {
this.basicTypeRegistry = basicTypeRegistry;
public TypeResolver(TypeConfiguration typeConfiguration, TypeFactory typeFactory){
this.basicTypeRegistry = typeConfiguration.getBasicTypeRegistry();
this.typeFactory = typeFactory;
}
public TypeResolver scope(SessionFactoryImplementor factory) {
typeFactory.injectSessionFactory( factory );
return new TypeResolver( basicTypeRegistry.shallowCopy(), typeFactory );
}
// public TypeResolver() {
// this( new BasicTypeRegistry(), new TypeFactory() );
// }
//
// /**
// * @deprecated (since 5.3)
// */
// @Deprecated
// public TypeResolver(BasicTypeRegistry basicTypeRegistry, TypeFactory typeFactory) {
// this.basicTypeRegistry = basicTypeRegistry;
// this.typeFactory = typeFactory;
// }
// public TypeResolver scope(SessionFactoryImplementor factory) {
// typeFactory.injectSessionFactory( factory );
// return new TypeResolver( basicTypeRegistry.shallowCopy(), typeFactory );
// }
public void registerTypeOverride(BasicType type) {
basicTypeRegistry.register( type );

View File

@ -0,0 +1,239 @@
/*
* 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.type.spi;
import java.io.Serializable;
import org.hibernate.HibernateException;
import org.hibernate.Incubating;
import org.hibernate.SessionFactory;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.boot.cfgxml.spi.CfgXmlAccessService;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.internal.SessionFactoryRegistry;
import org.hibernate.type.BasicTypeRegistry;
import org.hibernate.type.TypeFactory;
import org.hibernate.type.TypeResolver;
import org.jboss.logging.Logger;
import static org.hibernate.internal.CoreLogging.logger;
import static org.hibernate.internal.CoreLogging.messageLogger;
/**
* Defines a set of available Type instances as isolated from other configurations. The
* isolation is defined by each instance of a TypeConfiguration.
* <p/>
* Note that each Type is inherently "scoped" to a TypeConfiguration. We only ever access
* a Type through a TypeConfiguration - specifically the TypeConfiguration in effect for
* the current persistence unit.
* <p/>
* Even though each Type instance is scoped to a TypeConfiguration, Types do not inherently
* have access to that TypeConfiguration (mainly because Type is an extension contract - meaning
* that Hibernate does not manage the full set of Types available in ever TypeConfiguration).
* However Types will often want access to the TypeConfiguration, which can be achieved by the
* Type simply implementing the {@link TypeConfigurationAware} interface.
*
* @author Steve Ebersole
*
* @since 6.0
*/
@Incubating
public class TypeConfiguration implements SessionFactoryObserver, Serializable {
private static final CoreMessageLogger log = messageLogger( Scope.class );
// todo : (
private final Scope scope;
private final TypeFactory typeFactory;
private boolean initialized = false;
private final BasicTypeRegistry basicTypeRegistry;
// temporarily needed to support deprecations
private final TypeResolver typeResolver;
public TypeConfiguration() {
this.scope = new Scope( );
basicTypeRegistry = new BasicTypeRegistry();
typeFactory = new TypeFactory( this );
typeResolver = new TypeResolver( this, typeFactory );
this.initialized = true;
}
/**
* Temporarily needed to support deprecations
* @deprecated
*/
public TypeResolver getTypeResolver(){
return typeResolver;
}
public BasicTypeRegistry getBasicTypeRegistry() {
return basicTypeRegistry;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Scoping
/**
* Obtain the MetadataBuildingContext currently scoping the
* 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
*
* @return
*/
public MetadataBuildingContext getMetadataBuildingContext() {
return scope.getMetadataBuildingContext();
}
public void scope(MetadataBuildingContext metadataBuildingContext) {
log.debugf( "Scoping TypeConfiguration [%s] to MetadataBuildingContext [%s]", this, metadataBuildingContext );
scope.setMetadataBuildingContext( metadataBuildingContext );
}
public void scope(SessionFactoryImpl sessionFactory) {
log.debugf( "Scoping TypeConfiguration [%s] to SessionFactoryImpl [%s]", this, sessionFactory );
scope.setSessionFactory( sessionFactory );
typeFactory.injectSessionFactory( sessionFactory );
}
/**
* Obtain the SessionFactory currently scoping the 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 (this is "runtime stage")
*
* @return The SessionFactory
*
* @throws IllegalStateException if the TypeConfiguration is currently not
* associated with a SessionFactory (in "runtime stage").
*/
public SessionFactoryImplementor getSessionFactory() {
return scope.getSessionFactory();
}
@Override
public void sessionFactoryCreated(SessionFactory factory) {
// Instead of allowing scope#setSessionFactory to influence this, we use the SessionFactoryObserver callback
// to handle this, allowing any SessionFactory constructor code to be able to continue to have access to the
// MetadataBuildingContext through TypeConfiguration until this callback is fired.
log.tracef( "Handling #sessionFactoryCreated from [%s] for TypeConfiguration", factory );
scope.setMetadataBuildingContext( null );
}
@Override
public void sessionFactoryClosed(SessionFactory factory) {
log.tracef( "Handling #sessionFactoryClosed from [%s] for TypeConfiguration", factory );
scope.unsetSessionFactory( factory );
// todo (6.0) : finish this
// release Database, descriptor Maps, etc... things that are only
// valid while the TypeConfiguration is scoped to SessionFactory
}
/**
* Encapsulation of lifecycle concerns for a TypeConfiguration, mainly in
* regards to eventually being associated with a SessionFactory. Goes
* 3 "lifecycle" stages, pertaining to {@link #getMetadataBuildingContext()}
* and {@link #getSessionFactory()}:
*
* * "Initialization" is where the {@link TypeConfiguration} is first
* built as the "boot model" ({@link org.hibernate.boot.model}) of
* the user's domain model is converted into the "runtime model"
* ({@link org.hibernate.metamodel.model}). During this phase,
* {@link #getMetadataBuildingContext()} will be accessible but
* {@link #getSessionFactory} will throw an exception.
* * "Runtime" is where the "runtime model" is accessible while the
* SessionFactory is still unclosed. During this phase
* {@link #getSessionFactory()} is accessible while
* {@link #getMetadataBuildingContext()} will now throw an
* exception
* * "Sunset" is after the SessionFactory has been closed. During this
* phase both {@link #getSessionFactory()} and
* {@link #getMetadataBuildingContext()} will now throw an exception
*
* Each stage or phase is consider a "scope" for the TypeConfiguration.
*/
private static class Scope implements Serializable {
// todo (6.0) : consider a proper contract implemented by both SessionFactory (or its metamodel) and boot's MetadataImplementor
// 1) type-related info from MetadataBuildingOptions
// 2) ServiceRegistry
private transient MetadataBuildingContext metadataBuildingContext;
private transient SessionFactoryImplementor sessionFactory;
private String sessionFactoryName;
private String sessionFactoryUuid;
public MetadataBuildingContext getMetadataBuildingContext() {
if ( metadataBuildingContext == null ) {
throw new HibernateException( "TypeConfiguration is not currently scoped to MetadataBuildingContext" );
}
return metadataBuildingContext;
}
public void setMetadataBuildingContext(MetadataBuildingContext metadataBuildingContext) {
this.metadataBuildingContext = metadataBuildingContext;
}
public SessionFactoryImplementor getSessionFactory() {
if ( sessionFactory == null ) {
if ( sessionFactoryName == null && sessionFactoryUuid == null ) {
throw new HibernateException( "TypeConfiguration was not yet scoped to SessionFactory" );
}
sessionFactory = (SessionFactoryImplementor) SessionFactoryRegistry.INSTANCE.findSessionFactory(
sessionFactoryUuid,
sessionFactoryName
);
if ( sessionFactory == null ) {
throw new HibernateException(
"Could not find a SessionFactory [uuid=" + sessionFactoryUuid + ",name=" + sessionFactoryName + "]"
);
}
}
return sessionFactory;
}
/**
* Used by TypeFactory scoping.
*
* @param factory The SessionFactory that the TypeFactory is being bound to
*/
void setSessionFactory(SessionFactoryImplementor factory) {
if ( this.sessionFactory != null ) {
log.scopingTypesToSessionFactoryAfterAlreadyScoped( this.sessionFactory, factory );
}
else {
this.sessionFactoryUuid = factory.getUuid();
String sfName = factory.getSessionFactoryOptions().getSessionFactoryName();
if ( sfName == null ) {
final CfgXmlAccessService cfgXmlAccessService = factory.getServiceRegistry()
.getService( CfgXmlAccessService.class );
if ( cfgXmlAccessService.getAggregatedConfig() != null ) {
sfName = cfgXmlAccessService.getAggregatedConfig().getSessionFactoryName();
}
}
this.sessionFactoryName = sfName;
}
this.sessionFactory = factory;
}
public void unsetSessionFactory(SessionFactory factory) {
log.debugf( "Un-scoping TypeConfiguration [%s] from SessionFactory [%s]", this, factory );
this.sessionFactory = null;
}
}
}

View File

@ -0,0 +1,23 @@
/*
* 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.type.spi;
/**
* Optional contract for Types that would like to be part of the scoping process of the
* TypeConfiguration, specifically to receive access to the TypeConfiguration it is scoped
* to. For additional information on TypeConfiguration scoping, see {@link TypeConfiguration}
* <p/>
* Note that it is illegal for a Type to implement TypeConfigurationAware and at the same time
* be scoped to more than one TypeConfiguration. Hibernate will enforce this internally
* which is why {@link #getTypeConfiguration()} is exposed here.
*
* @author Steve Ebersole
*/
public interface TypeConfigurationAware {
TypeConfiguration getTypeConfiguration();
void setTypeConfiguration(TypeConfiguration typeConfiguration);
}

View File

@ -24,6 +24,7 @@ import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.ClassLoaderAccess;
import org.hibernate.boot.spi.MetadataBuildingOptions;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.type.spi.TypeConfiguration;
import org.jboss.jandex.IndexView;
@ -47,6 +48,11 @@ public class BootstrapContextImpl implements BootstrapContext {
return delegate.getServiceRegistry();
}
@Override
public TypeConfiguration getTypeConfiguration() {
return delegate.getTypeConfiguration();
}
@Override
public MetadataBuildingOptions getMetadataBuildingOptions() {
return delegate.getMetadataBuildingOptions();

View File

@ -39,7 +39,7 @@ public class MetadataBuildingContextTestingImpl implements MetadataBuildingConte
buildingOptions = new MetadataBuilderImpl.MetadataBuildingOptionsImpl( serviceRegistry );
bootstrapContext = new BootstrapContextImpl( serviceRegistry, buildingOptions );
mappingDefaults = new MetadataBuilderImpl.MappingDefaultsImpl( serviceRegistry );
metadataCollector = new InFlightMetadataCollectorImpl( bootstrapContext,buildingOptions, new TypeResolver() );
metadataCollector = new InFlightMetadataCollectorImpl( bootstrapContext, buildingOptions );
objectNameNormalizer = new ObjectNameNormalizer() {
@Override