From f20d36be403a2c9afb8d8104ab0d8cb2fb463bf3 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Wed, 29 May 2019 20:53:04 +0100 Subject: [PATCH] 6 - SQM based on JPA type system, RuntimeModelCreationProcess --- .../internal/AttributeFactory.java | 12 +- .../internal/InflightRuntimeMetamodel.java | 389 ++++++++++++- .../domain => }/internal/MetadataContext.java | 27 +- .../internal/RuntimeModelCreationProcess.java | 135 ++++- .../model/domain/AbstractDomainType.java | 11 +- .../domain/AbstractIdentifiableType.java | 5 +- .../model/domain/AbstractManagedType.java | 5 +- .../domain/internal/DomainMetamodelImpl.java | 313 +--------- .../domain/internal/EmbeddableTypeImpl.java | 10 +- .../model/domain/internal/EntityTypeImpl.java | 6 +- .../domain/internal/JpaMetamodelImpl.java | 546 +++++++----------- .../internal/MappedSuperclassTypeImpl.java | 7 +- .../org/hibernate/type/AssociationType.java | 20 +- .../hibernate/type/spi/TypeConfiguration.java | 2 +- .../jpa/test/metadata/MetadataTest.java | 4 +- 15 files changed, 803 insertions(+), 689 deletions(-) rename hibernate-core/src/main/java/org/hibernate/metamodel/{model/domain => }/internal/AttributeFactory.java (98%) rename hibernate-core/src/main/java/org/hibernate/metamodel/{model/domain => }/internal/MetadataContext.java (96%) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AttributeFactory.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java similarity index 98% rename from hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AttributeFactory.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java index 7311537018..20ded75a79 100755 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AttributeFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.metamodel.model.domain.internal; +package org.hibernate.metamodel.internal; import java.lang.reflect.Field; import java.lang.reflect.Member; @@ -40,6 +40,11 @@ import org.hibernate.metamodel.model.domain.PersistentAttribute; import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.metamodel.model.domain.SimpleDomainType; import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; +import org.hibernate.metamodel.model.domain.internal.EmbeddableTypeImpl; +import org.hibernate.metamodel.model.domain.internal.MapMember; +import org.hibernate.metamodel.model.domain.internal.MappedSuperclassTypeImpl; +import org.hibernate.metamodel.model.domain.internal.PluralAttributeBuilder; +import org.hibernate.metamodel.model.domain.internal.SingularAttributeImpl; import org.hibernate.property.access.internal.PropertyAccessMapImpl; import org.hibernate.property.access.spi.Getter; import org.hibernate.tuple.entity.EntityMetamodel; @@ -293,9 +298,8 @@ public class AttributeFactory { private EntityMetamodel getDeclarerEntityMetamodel(AbstractIdentifiableType ownerType) { final Type.PersistenceType persistenceType = ownerType.getPersistenceType(); if ( persistenceType == Type.PersistenceType.ENTITY ) { - return context.getSessionFactory() - .getMetamodel() - .entityPersister( ownerType.getTypeName() ) + return context.getMetamodel() + .getEntityDescriptor( ownerType.getTypeName() ) .getEntityMetamodel(); } else if ( persistenceType == Type.PersistenceType.MAPPED_SUPERCLASS ) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/InflightRuntimeMetamodel.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/InflightRuntimeMetamodel.java index 711c4c4cb3..690814581d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/InflightRuntimeMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/InflightRuntimeMetamodel.java @@ -7,21 +7,48 @@ package org.hibernate.metamodel.internal; import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArraySet; import org.hibernate.EntityNameResolver; +import org.hibernate.HibernateException; +import org.hibernate.boot.spi.MetadataImplementor; +import org.hibernate.cache.spi.CacheImplementor; +import org.hibernate.cache.spi.access.CollectionDataAccess; +import org.hibernate.cache.spi.access.EntityDataAccess; +import org.hibernate.cache.spi.access.NaturalIdDataAccess; +import org.hibernate.internal.EntityManagerMessageLogger; +import org.hibernate.internal.HEMLogging; +import org.hibernate.mapping.Collection; +import org.hibernate.mapping.MappedSuperclass; +import org.hibernate.mapping.PersistentClass; import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.IdentifiableDomainType; import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType; +import org.hibernate.metamodel.model.domain.NavigableRole; +import org.hibernate.metamodel.model.domain.internal.EntityTypeImpl; +import org.hibernate.metamodel.model.domain.internal.MappedSuperclassTypeImpl; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.persister.spi.PersisterCreationContext; +import org.hibernate.persister.spi.PersisterFactory; +import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder; +import org.hibernate.tuple.entity.EntityTuplizer; +import org.hibernate.type.EntityType; +import org.hibernate.type.Type; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.spi.TypeConfiguration; /** * @author Steve Ebersole */ public class InflightRuntimeMetamodel { + private static final EntityManagerMessageLogger log = HEMLogging.messageLogger( InflightRuntimeMetamodel.class ); private final TypeConfiguration typeConfiguration; @@ -29,28 +56,372 @@ public class InflightRuntimeMetamodel { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Hibernate metamodel - private final Map entityPersisterMap = new HashMap<>(); - private Map entityProxyInterfaceMap; - private Map collectionPersisterMap; - private Map> collectionRolesByEntityParticipant; + private final Map entityPersisterMap = new ConcurrentHashMap<>(); + private final Map entityProxyInterfaceMap = new ConcurrentHashMap<>(); + private final Map collectionPersisterMap = new ConcurrentHashMap<>(); + private final Map> collectionRolesByEntityParticipant = new ConcurrentHashMap<>(); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // JPA metamodel - private final Map> jpaEntityTypeMap = new HashMap<>(); - private Map> jpaMappedSuperclassTypeMap; - private Map> embeddableDescriptorMap; + private final Map> jpaEntityTypeMap = new ConcurrentHashMap<>(); + private final Map, MappedSuperclassDomainType> jpaMappedSuperclassTypeMap = new ConcurrentHashMap<>(); + private Map> jpaEmbeddableDescriptorMap = new ConcurrentHashMap<>(); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Misc private final Map nameToImportNameMap = new HashMap<>(); - private Set entityNameResolvers; - + private final Set entityNameResolvers = new CopyOnWriteArraySet<>(); public InflightRuntimeMetamodel(TypeConfiguration typeConfiguration) { this.typeConfiguration = typeConfiguration; } + + public void processBootMetaModel( + MetadataImplementor bootMetamodel, + SqmCriteriaNodeBuilder criteriaBuilder, + CacheImplementor cacheImplementor, + PersisterFactory persisterFactory, + PersisterCreationContext persisterCreationContext, + JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting, + JpaStaticMetaModelPopulationSetting jpaStaticMetaModelPopulationSetting) { + processBootEntities( + bootMetamodel.getEntityBindings(), + cacheImplementor, + persisterFactory, + persisterCreationContext + ); + + processBootCollections( + bootMetamodel.getCollectionBindings(), + cacheImplementor, + persisterFactory, + persisterCreationContext + ); + + finishDomainMetamodelInitialization(); + + processJpa( + bootMetamodel, + criteriaBuilder, + jpaMetaModelPopulationSetting, + jpaStaticMetaModelPopulationSetting + ); + + } + + public TypeConfiguration getTypeConfiguration() { + return typeConfiguration; + } + + public Map getEntityPersisterMap() { + return entityPersisterMap; + } + + public Map getEntityProxyInterfaceMap() { + return entityProxyInterfaceMap; + } + + public Map getCollectionPersisterMap() { + return collectionPersisterMap; + } + + public Map> getCollectionRolesByEntityParticipant() { + return collectionRolesByEntityParticipant; + } + + public Map> getJpaEntityTypeMap() { + return jpaEntityTypeMap; + } + + public Map, MappedSuperclassDomainType> getJpaMappedSuperclassTypeMap() { + return jpaMappedSuperclassTypeMap; + } + + public Map> getJpaEmbeddableDescriptorMap() { + return jpaEmbeddableDescriptorMap; + } + + public Map getNameToImportNameMap() { + return nameToImportNameMap; + } + + public Set getEntityNameResolvers() { + return entityNameResolvers; + } + + /** + * Get an entity mapping descriptor based on its Hibernate entity-name + * + * @throws IllegalArgumentException if the name does not refer to an entity + */ + public EntityPersister getEntityDescriptor(String entityName) { + final EntityPersister entityPersister = entityPersisterMap.get( entityName ); + if ( entityPersister == null ) { + throw new IllegalArgumentException( "Unable to locate persister: " + entityName ); + } + return entityPersister; + } + + /** + * Find an entity mapping descriptor based on its Hibernate entity-name. + * + * @apiNote Returns {@code null} rather than throwing exception + */ + public EntityPersister findEntityDescriptor(String entityName) { + return entityPersisterMap.get( entityName ); + } + + private void processJpa( + MetadataImplementor bootMetamodel, + SqmCriteriaNodeBuilder criteriaBuilder, + JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting, + JpaStaticMetaModelPopulationSetting jpaStaticMetaModelPopulationSetting) { + if ( jpaMetaModelPopulationSetting != JpaMetaModelPopulationSetting.DISABLED ) { + + MetadataContext context = new MetadataContext( + this, + criteriaBuilder, + bootMetamodel.getMappedSuperclassMappingsCopy(), + typeConfiguration, + jpaMetaModelPopulationSetting, + jpaStaticMetaModelPopulationSetting + ); + + for ( PersistentClass entityBinding : bootMetamodel.getEntityBindings() ) { + locateOrBuildEntityType( entityBinding, context ); + } + handleUnusedMappedSuperclasses( context ); + + context.wrapUp(); + + this.nameToImportNameMap.putAll( bootMetamodel.getImports() ); + + this.jpaEntityTypeMap.putAll( context.getEntityTypesByEntityName() ); + this.jpaMappedSuperclassTypeMap.putAll( context.getMappedSuperclassTypeMap() ); + + for ( EmbeddableDomainType embeddable : context.getEmbeddableTypeSet() ) { + this.jpaEmbeddableDescriptorMap.put( embeddable.getJavaType(), embeddable ); + } + + } + } + + private void processBootEntities( + java.util.Collection entityBindings, + CacheImplementor cacheImplementor, + PersisterFactory persisterFactory, + PersisterCreationContext persisterCreationContext) { + for ( final PersistentClass model : entityBindings ) { + final NavigableRole rootEntityRole = new NavigableRole( model.getRootClass().getEntityName() ); + final EntityDataAccess accessStrategy = cacheImplementor.getEntityRegionAccess( rootEntityRole ); + final NaturalIdDataAccess naturalIdAccessStrategy = cacheImplementor + .getNaturalIdCacheRegionAccessStrategy( rootEntityRole ); + + final EntityPersister cp = persisterFactory.createEntityPersister( + model, + accessStrategy, + naturalIdAccessStrategy, + persisterCreationContext + ); + entityPersisterMap.put( model.getEntityName(), cp ); + + if ( cp.getConcreteProxyClass() != null + && cp.getConcreteProxyClass().isInterface() + && !Map.class.isAssignableFrom( cp.getConcreteProxyClass() ) + && cp.getMappedClass() != cp.getConcreteProxyClass() ) { + // IMPL NOTE : we exclude Map based proxy interfaces here because that should + // indicate MAP entity mode.0 + + if ( cp.getMappedClass().equals( cp.getConcreteProxyClass() ) ) { + // this part handles an odd case in the Hibernate test suite where we map an interface + // as the class and the proxy. I cannot think of a real life use case for that + // specific test, but.. + log.debugf( + "Entity [%s] mapped same interface [%s] as class and proxy", + cp.getEntityName(), + cp.getMappedClass() + ); + } + else { + final String old = entityProxyInterfaceMap.put( cp.getConcreteProxyClass(), cp.getEntityName() ); + if ( old != null ) { + throw new HibernateException( + String.format( + Locale.ENGLISH, + "Multiple entities [%s, %s] named the same interface [%s] as their proxy which is not supported", + old, + cp.getEntityName(), + cp.getConcreteProxyClass().getName() + ) + ); + } + } + } + } + } + + private void processBootCollections( + java.util.Collection collectionBindings, + CacheImplementor cacheImplementor, + PersisterFactory persisterFactory, + PersisterCreationContext persisterCreationContext) { + for ( final Collection model : collectionBindings ) { + final NavigableRole navigableRole = new NavigableRole( model.getRole() ); + + final CollectionDataAccess accessStrategy = cacheImplementor.getCollectionRegionAccess( + navigableRole ); + + final CollectionPersister persister = persisterFactory.createCollectionPersister( + model, + accessStrategy, + persisterCreationContext + ); + collectionPersisterMap.put( model.getRole(), persister ); + Type indexType = persister.getIndexType(); + if ( indexType != null && indexType.isEntityType() && !indexType.isAnyType() ) { + String entityName = ( (EntityType) indexType ).getAssociatedEntityName(); + Set roles = collectionRolesByEntityParticipant.get( entityName ); + if ( roles == null ) { + roles = new HashSet<>(); + collectionRolesByEntityParticipant.put( entityName, roles ); + } + roles.add( persister.getRole() ); + } + Type elementType = persister.getElementType(); + if ( elementType.isEntityType() && !elementType.isAnyType() ) { + String entityName = ( (EntityType) elementType ).getAssociatedEntityName(); + Set roles = collectionRolesByEntityParticipant.get( entityName ); + if ( roles == null ) { + roles = new HashSet<>(); + collectionRolesByEntityParticipant.put( entityName, roles ); + } + roles.add( persister.getRole() ); + } + } + } + + private void finishDomainMetamodelInitialization() { + // after *all* persisters and named queries are registered + entityPersisterMap.values().forEach( EntityPersister::generateEntityDefinition ); + + for ( EntityPersister persister : entityPersisterMap.values() ) { + persister.postInstantiate(); + registerEntityNameResolvers( persister, entityNameResolvers ); + } + collectionPersisterMap.values().forEach( CollectionPersister::postInstantiate ); + } + + private static void registerEntityNameResolvers( + EntityPersister persister, + Set entityNameResolvers) { + if ( persister.getEntityMetamodel() == null || persister.getEntityMetamodel().getTuplizer() == null ) { + return; + } + registerEntityNameResolvers( persister.getEntityMetamodel().getTuplizer(), entityNameResolvers ); + } + + private static void registerEntityNameResolvers( + EntityTuplizer tuplizer, + Set entityNameResolvers) { + EntityNameResolver[] resolvers = tuplizer.getEntityNameResolvers(); + if ( resolvers == null ) { + return; + } + + for ( EntityNameResolver resolver : resolvers ) { + entityNameResolvers.add( resolver ); + } + } + + private static void handleUnusedMappedSuperclasses(MetadataContext context) { + final Set unusedMappedSuperclasses = context.getUnusedMappedSuperclasses(); + if ( !unusedMappedSuperclasses.isEmpty() ) { + for ( MappedSuperclass mappedSuperclass : unusedMappedSuperclasses ) { + log.unusedMappedSuperclass( mappedSuperclass.getMappedClass().getName() ); + locateOrBuildMappedSuperclassType( mappedSuperclass, context ); + } + } + } + + private static MappedSuperclassDomainType locateOrBuildMappedSuperclassType( + MappedSuperclass mappedSuperclass, + MetadataContext context) { + MappedSuperclassDomainType mappedSuperclassType = context.locateMappedSuperclassType( mappedSuperclass ); + if ( mappedSuperclassType == null ) { + mappedSuperclassType = buildMappedSuperclassType( mappedSuperclass, context ); + } + return mappedSuperclassType; + } + + @SuppressWarnings("unchecked") + private static MappedSuperclassTypeImpl buildMappedSuperclassType( + MappedSuperclass mappedSuperclass, + MetadataContext context) { + final MappedSuperclass superMappedSuperclass = mappedSuperclass.getSuperMappedSuperclass(); + IdentifiableDomainType superType = superMappedSuperclass == null + ? null + : locateOrBuildMappedSuperclassType( superMappedSuperclass, context ); + //no mappedSuperclass, check for a super entity + if ( superType == null ) { + final PersistentClass superPersistentClass = mappedSuperclass.getSuperPersistentClass(); + superType = superPersistentClass == null + ? null + : locateOrBuildEntityType( superPersistentClass, context ); + } + final JavaTypeDescriptor javaTypeDescriptor = context.getTypeConfiguration() + .getJavaTypeDescriptorRegistry() + .getDescriptor( mappedSuperclass.getMappedClass() ); + MappedSuperclassTypeImpl mappedSuperclassType = new MappedSuperclassTypeImpl( + javaTypeDescriptor, + mappedSuperclass, + superType + ); + + context.registerMappedSuperclassType( mappedSuperclass, mappedSuperclassType ); + return mappedSuperclassType; + } + + private static EntityDomainType locateOrBuildEntityType( + PersistentClass persistentClass, + MetadataContext context) { + EntityDomainType entityType = context.locateEntityType( persistentClass ); + if ( entityType == null ) { + entityType = buildEntityType( persistentClass, context ); + } + return entityType; + } + + @SuppressWarnings("unchecked") + private static EntityTypeImpl buildEntityType(PersistentClass persistentClass, MetadataContext context) { + final Class javaType = persistentClass.getMappedClass(); + context.pushEntityWorkedOn( persistentClass ); + final MappedSuperclass superMappedSuperclass = persistentClass.getSuperMappedSuperclass(); + IdentifiableDomainType superType = superMappedSuperclass == null + ? null + : locateOrBuildMappedSuperclassType( superMappedSuperclass, context ); + //no mappedSuperclass, check for a super entity + if ( superType == null ) { + final PersistentClass superPersistentClass = persistentClass.getSuperclass(); + superType = superPersistentClass == null + ? null + : locateOrBuildEntityType( superPersistentClass, context ); + } + + final JavaTypeDescriptor javaTypeDescriptor = context.getTypeConfiguration() + .getJavaTypeDescriptorRegistry() + .getDescriptor( javaType ); + EntityTypeImpl entityType = new EntityTypeImpl( + javaTypeDescriptor, + superType, + persistentClass + ); + context.registerEntityType( persistentClass, entityType ); + context.popEntityWorkedOn( persistentClass ); + return entityType; + } + } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MetadataContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MetadataContext.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java index 2b48885e1a..7c8c2cfe90 100755 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MetadataContext.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.metamodel.model.domain.internal; +package org.hibernate.metamodel.internal; import java.lang.reflect.Field; import java.util.ArrayList; @@ -17,13 +17,10 @@ import java.util.Map; import java.util.Set; import javax.persistence.metamodel.Attribute; import javax.persistence.metamodel.IdentifiableType; -import javax.persistence.metamodel.MappedSuperclassType; -import javax.persistence.metamodel.Metamodel; import javax.persistence.metamodel.SingularAttribute; import javax.persistence.metamodel.Type; import org.hibernate.annotations.common.AssertionFailure; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.EntityManagerMessageLogger; import org.hibernate.internal.HEMLogging; import org.hibernate.internal.util.ReflectHelper; @@ -33,20 +30,20 @@ import org.hibernate.mapping.KeyValue; import org.hibernate.mapping.MappedSuperclass; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; -import org.hibernate.metamodel.internal.JpaMetaModelPopulationSetting; -import org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting; import org.hibernate.metamodel.model.domain.AbstractIdentifiableType; import org.hibernate.metamodel.model.domain.BasicDomainType; import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.IdentifiableDomainType; -import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType; import org.hibernate.metamodel.model.domain.PersistentAttribute; import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; -import org.hibernate.metamodel.spi.DomainMetamodel; -import org.hibernate.metamodel.spi.MetamodelImplementor; +import org.hibernate.metamodel.model.domain.internal.AttributeContainer; +import org.hibernate.metamodel.model.domain.internal.BasicTypeImpl; +import org.hibernate.metamodel.model.domain.internal.DomainMetamodelImpl; +import org.hibernate.metamodel.model.domain.internal.EntityTypeImpl; +import org.hibernate.metamodel.model.domain.internal.MappedSuperclassTypeImpl; import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder; import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry; import org.hibernate.type.spi.TypeConfiguration; @@ -90,10 +87,10 @@ class MetadataContext { * Stack of PersistentClass being process. Last in the list is the highest in the stack. */ private List stackOfPersistentClassesBeingProcessed = new ArrayList<>(); - private DomainMetamodel metamodel; + private InflightRuntimeMetamodel metamodel; public MetadataContext( - DomainMetamodel metamodel, + InflightRuntimeMetamodel metamodel, SqmCriteriaNodeBuilder criteriaBuilder, Set mappedSuperclasses, TypeConfiguration typeConfiguration, @@ -120,7 +117,7 @@ class MetadataContext { return typeConfiguration.getJavaTypeDescriptorRegistry(); } - DomainMetamodel getMetamodel() { + InflightRuntimeMetamodel getMetamodel() { return metamodel; } @@ -141,9 +138,9 @@ class MetadataContext { return new HashSet<>( embeddables.values() ); } - public Map, MappedSuperclassType> getMappedSuperclassTypeMap() { + public Map, MappedSuperclassDomainType> getMappedSuperclassTypeMap() { // we need to actually build this map... - final Map, MappedSuperclassType> mappedSuperClassTypeMap = CollectionHelper.mapOfSize( + final Map, MappedSuperclassDomainType> mappedSuperClassTypeMap = CollectionHelper.mapOfSize( mappedSuperclassByMappedSuperclassMapping.size() ); @@ -267,7 +264,7 @@ class MetadataContext { } final PersistentAttribute attribute = attributeFactory.buildAttribute( jpaMapping, property ); if ( attribute != null ) { - ( ( AttributeContainer) jpaMapping ).getInFlightAccess().addAttribute( attribute ); + ( (AttributeContainer) jpaMapping ).getInFlightAccess().addAttribute( attribute ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/RuntimeModelCreationProcess.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/RuntimeModelCreationProcess.java index e7225ffeae..296ecac59e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/RuntimeModelCreationProcess.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/RuntimeModelCreationProcess.java @@ -6,12 +6,28 @@ */ package org.hibernate.metamodel.internal; -import org.hibernate.NotYetImplementedFor6Exception; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + import org.hibernate.boot.spi.BootstrapContext; import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.MetadataImplementor; +import org.hibernate.cache.cfg.internal.DomainDataRegionConfigImpl; +import org.hibernate.cache.cfg.spi.DomainDataRegionConfig; +import org.hibernate.cache.spi.access.AccessType; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.mapping.Collection; +import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.RootClass; +import org.hibernate.metamodel.model.domain.JpaMetamodel; +import org.hibernate.metamodel.model.domain.internal.DomainMetamodelImpl; +import org.hibernate.metamodel.model.domain.internal.JpaMetamodelImpl; import org.hibernate.metamodel.spi.MetamodelImplementor; +import org.hibernate.persister.spi.PersisterCreationContext; +import org.hibernate.persister.spi.PersisterFactory; import static org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting.determineJpaMetaModelPopulationSetting; @@ -19,10 +35,9 @@ import static org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetti * Responsible for interpreting the Hibernate boot metamodel into * its runtime metamodel * + * @author Steve Ebersole * @see org.hibernate.boot.model * @see org.hibernate.metamodel - * - * @author Steve Ebersole */ public class RuntimeModelCreationProcess { @@ -76,31 +91,131 @@ public class RuntimeModelCreationProcess { SessionFactoryImplementor sessionFactory, BootstrapContext bootstrapContext, MetadataBuildingContext metadataBuildingContext, - MetadataImplementor bootMetamodel) { - return new RuntimeModelCreationProcess( sessionFactory, bootstrapContext, metadataBuildingContext ).execute(); + MetadataImplementor bootMetamodel, + JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting) { + return new RuntimeModelCreationProcess( + sessionFactory, + bootstrapContext, + metadataBuildingContext, + bootMetamodel, + jpaMetaModelPopulationSetting + ).execute(); } private final SessionFactoryImplementor sessionFactory; private final BootstrapContext bootstrapContext; private final MetadataBuildingContext metadataBuildingContext; + private final MetadataImplementor bootMetamodel; + private final JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting; + + private JpaMetamodel jpaMetamodel; + private MetamodelImplementor domainMetamodel; public RuntimeModelCreationProcess( SessionFactoryImplementor sessionFactory, BootstrapContext bootstrapContext, - MetadataBuildingContext metadataBuildingContext) { + MetadataBuildingContext metadataBuildingContext, + MetadataImplementor bootMetamodel, + JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting) { this.sessionFactory = sessionFactory; this.bootstrapContext = bootstrapContext; this.metadataBuildingContext = metadataBuildingContext; + this.bootMetamodel = bootMetamodel; + this.jpaMetaModelPopulationSetting = jpaMetaModelPopulationSetting; } - public MetamodelImplementor execute() { + final PersisterCreationContext persisterCreationContext = new PersisterCreationContext() { + @Override + public SessionFactoryImplementor getSessionFactory() { + return sessionFactory; + } + + @Override + public MetadataImplementor getMetadata() { + return bootMetamodel; + } + }; + + final PersisterFactory persisterFactory = sessionFactory.getServiceRegistry() + .getService( PersisterFactory.class ); final InflightRuntimeMetamodel inflightRuntimeMetamodel = new InflightRuntimeMetamodel( bootstrapContext.getTypeConfiguration() ); - final JpaStaticMetaModelPopulationSetting jpaStaticMetaModelPopulationSetting = determineJpaMetaModelPopulationSetting( - sessionFactory.getProperties() + + primeSecondLevelCacheRegions( bootMetamodel ); + + inflightRuntimeMetamodel.processBootMetaModel( + bootMetamodel, + sessionFactory.getQueryEngine().getCriteriaBuilder(), + sessionFactory.getCache(), + persisterFactory, + persisterCreationContext, + jpaMetaModelPopulationSetting, + determineJpaMetaModelPopulationSetting( + sessionFactory.getProperties() ) + ); - throw new NotYetImplementedFor6Exception(); + this.jpaMetamodel = new JpaMetamodelImpl( + inflightRuntimeMetamodel, + bootMetamodel.getNamedEntityGraphs().values() + ); + + this.domainMetamodel = new DomainMetamodelImpl( sessionFactory, inflightRuntimeMetamodel, this.jpaMetamodel ); + return domainMetamodel; + } + + private void primeSecondLevelCacheRegions(MetadataImplementor mappingMetadata) { + final Map regionConfigBuilders = new ConcurrentHashMap<>(); + + // todo : ultimately this code can be made more efficient when we have a better intrinsic understanding of the hierarchy as a whole + + for ( PersistentClass bootEntityDescriptor : mappingMetadata.getEntityBindings() ) { + final AccessType accessType = AccessType.fromExternalName( bootEntityDescriptor.getCacheConcurrencyStrategy() ); + + if ( accessType != null ) { + if ( bootEntityDescriptor.isCached() ) { + regionConfigBuilders.computeIfAbsent( + bootEntityDescriptor.getRootClass().getCacheRegionName(), + DomainDataRegionConfigImpl.Builder::new + ) + .addEntityConfig( bootEntityDescriptor, accessType ); + } + + if ( RootClass.class.isInstance( bootEntityDescriptor ) + && bootEntityDescriptor.hasNaturalId() + && bootEntityDescriptor.getNaturalIdCacheRegionName() != null ) { + regionConfigBuilders.computeIfAbsent( + bootEntityDescriptor.getNaturalIdCacheRegionName(), + DomainDataRegionConfigImpl.Builder::new + ) + .addNaturalIdConfig( (RootClass) bootEntityDescriptor, accessType ); + } + } + } + + for ( Collection collection : mappingMetadata.getCollectionBindings() ) { + final AccessType accessType = AccessType.fromExternalName( collection.getCacheConcurrencyStrategy() ); + if ( accessType != null ) { + regionConfigBuilders.computeIfAbsent( + collection.getCacheRegionName(), + DomainDataRegionConfigImpl.Builder::new + ) + .addCollectionConfig( collection, accessType ); + } + } + + final Set regionConfigs; + if ( regionConfigBuilders.isEmpty() ) { + regionConfigs = Collections.emptySet(); + } + else { + regionConfigs = new HashSet<>(); + for ( DomainDataRegionConfigImpl.Builder builder : regionConfigBuilders.values() ) { + regionConfigs.add( builder.build() ); + } + } + + sessionFactory.getCache().prime( regionConfigs ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractDomainType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractDomainType.java index ab51963038..1926c9134d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractDomainType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractDomainType.java @@ -12,22 +12,23 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor; * @author Steve Ebersole */ public abstract class AbstractDomainType implements SimpleDomainType { - private final JpaMetamodel jpaMetamodel; + private JpaMetamodel jpaMetamodel; private final JavaTypeDescriptor javaTypeDescriptor; @SuppressWarnings("WeakerAccess") - public AbstractDomainType( - JavaTypeDescriptor javaTypeDescriptor, - JpaMetamodel jpaMetamodel) { + public AbstractDomainType(JavaTypeDescriptor javaTypeDescriptor) { this.javaTypeDescriptor = javaTypeDescriptor; - this.jpaMetamodel = jpaMetamodel; } protected JpaMetamodel jpaMetamodel() { return jpaMetamodel; } + public void injectJpaMetamodel(JpaMetamodel jpaMetamodel){ + this.jpaMetamodel = jpaMetamodel; + } + @Override public JavaTypeDescriptor getExpressableJavaTypeDescriptor() { return javaTypeDescriptor; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractIdentifiableType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractIdentifiableType.java index 9ec808e8d3..ebed24b7ee 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractIdentifiableType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractIdentifiableType.java @@ -45,9 +45,8 @@ public abstract class AbstractIdentifiableType IdentifiableDomainType superType, boolean hasIdClass, boolean hasIdentifierProperty, - boolean versioned, - JpaMetamodel jpaMetamodel) { - super( typeName, javaTypeDescriptor, superType, jpaMetamodel ); + boolean versioned) { + super( typeName, javaTypeDescriptor, superType ); this.hasIdClass = hasIdClass; this.hasIdentifierProperty = hasIdentifierProperty; this.isVersioned = versioned; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractManagedType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractManagedType.java index cfdce44c79..12fc942be2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractManagedType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractManagedType.java @@ -48,9 +48,8 @@ public abstract class AbstractManagedType protected AbstractManagedType( String hibernateTypeName, JavaTypeDescriptor javaTypeDescriptor, - ManagedDomainType superType, - JpaMetamodel jpaMetamodel) { - super( javaTypeDescriptor, jpaMetamodel ); + ManagedDomainType superType) { + super( javaTypeDescriptor ); this.hibernateTypeName = hibernateTypeName; this.superType = superType; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DomainMetamodelImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DomainMetamodelImpl.java index 75289ac81c..bdd4b89a66 100755 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DomainMetamodelImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DomainMetamodelImpl.java @@ -9,14 +9,10 @@ package org.hibernate.metamodel.model.domain.internal; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import java.util.function.Consumer; import javax.persistence.EntityGraph; import javax.persistence.metamodel.EmbeddableType; @@ -24,44 +20,26 @@ import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.ManagedType; import org.hibernate.EntityNameResolver; -import org.hibernate.HibernateException; import org.hibernate.MappingException; import org.hibernate.UnknownEntityTypeException; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; -import org.hibernate.boot.spi.MetadataImplementor; -import org.hibernate.cache.cfg.internal.DomainDataRegionConfigImpl; -import org.hibernate.cache.cfg.spi.DomainDataRegionConfig; -import org.hibernate.cache.spi.access.AccessType; -import org.hibernate.cache.spi.access.CollectionDataAccess; -import org.hibernate.cache.spi.access.EntityDataAccess; -import org.hibernate.cache.spi.access.NaturalIdDataAccess; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.graph.RootGraph; import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.internal.EntityManagerMessageLogger; import org.hibernate.internal.HEMLogging; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.RootClass; -import org.hibernate.metamodel.internal.JpaMetaModelPopulationSetting; -import org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting; -import org.hibernate.metamodel.model.domain.JpaMetamodel; -import org.hibernate.metamodel.model.domain.NavigableRole; +import org.hibernate.metamodel.internal.InflightRuntimeMetamodel; import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.spi.DomainMetamodel; import org.hibernate.metamodel.spi.MetamodelImplementor; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.Queryable; -import org.hibernate.persister.spi.PersisterCreationContext; -import org.hibernate.persister.spi.PersisterFactory; -import org.hibernate.tuple.entity.EntityTuplizer; -import org.hibernate.type.AssociationType; -import org.hibernate.type.Type; import org.hibernate.type.spi.TypeConfiguration; /** @@ -84,7 +62,7 @@ public class DomainMetamodelImpl implements DomainMetamodel, MetamodelImplemento // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // JpaMetamodel - private final JpaMetamodelImpl jpaMetamodel; + private final JpaMetamodel jpaMetamodel; // private final Map, EntityDomainType> jpaEntityTypeMap = new ConcurrentHashMap<>(); // private final Map> jpaEntityTypesByEntityName = new ConcurrentHashMap<>(); @@ -96,15 +74,15 @@ public class DomainMetamodelImpl implements DomainMetamodel, MetamodelImplemento // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // RuntimeModel - private final Map entityPersisterMap = new ConcurrentHashMap<>(); - private final Map collectionPersisterMap = new ConcurrentHashMap<>(); - private final Map> collectionRolesByEntityParticipant = new ConcurrentHashMap<>(); + private final Map entityPersisterMap; + private final Map collectionPersisterMap; + private final Map> collectionRolesByEntityParticipant; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // DomainMetamodel - private final ConcurrentMap entityNameResolvers = new ConcurrentHashMap<>(); + private final Set entityNameResolvers; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -143,254 +121,25 @@ public class DomainMetamodelImpl implements DomainMetamodel, MetamodelImplemento private final Map implementorsCache = new ConcurrentHashMap<>(); - public DomainMetamodelImpl(SessionFactoryImplementor sessionFactory, TypeConfiguration typeConfiguration) { + public DomainMetamodelImpl( + SessionFactoryImplementor sessionFactory, + InflightRuntimeMetamodel runtimeMetamodel, + JpaMetamodel jpaMetamodel) { this.sessionFactory = sessionFactory; - this.typeConfiguration = typeConfiguration; - this.jpaMetamodel = new JpaMetamodelImpl( typeConfiguration ); + this.jpaMetamodel = jpaMetamodel; + this.typeConfiguration = runtimeMetamodel.getTypeConfiguration(); + this.entityPersisterMap = runtimeMetamodel.getEntityPersisterMap(); + this.collectionPersisterMap = runtimeMetamodel.getCollectionPersisterMap(); + this.collectionRolesByEntityParticipant = runtimeMetamodel.getCollectionRolesByEntityParticipant(); + this.entityNameResolvers = runtimeMetamodel.getEntityNameResolvers(); + } - /** - * Prepare the metamodel using the information from the collection of Hibernate - * {@link PersistentClass} models - * - * @param mappingMetadata The mapping information - * @param jpaMetaModelPopulationSetting Should the JPA Metamodel be built as well? - */ - public void initialize( - MetadataImplementor mappingMetadata, - JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting) { - - primeSecondLevelCacheRegions( mappingMetadata ); - - final PersisterCreationContext persisterCreationContext = new PersisterCreationContext() { - @Override - public SessionFactoryImplementor getSessionFactory() { - return sessionFactory; - } - - @Override - public MetadataImplementor getMetadata() { - return mappingMetadata; - } - }; - - final PersisterFactory persisterFactory = sessionFactory.getServiceRegistry() - .getService( PersisterFactory.class ); - - for ( final PersistentClass model : mappingMetadata.getEntityBindings() ) { - final NavigableRole rootEntityRole = new NavigableRole( model.getRootClass().getEntityName() ); - final EntityDataAccess accessStrategy = sessionFactory.getCache().getEntityRegionAccess( rootEntityRole ); - final NaturalIdDataAccess naturalIdAccessStrategy = sessionFactory.getCache() - .getNaturalIdCacheRegionAccessStrategy( rootEntityRole ); - - final EntityPersister cp = persisterFactory.createEntityPersister( - model, - accessStrategy, - naturalIdAccessStrategy, - persisterCreationContext - ); - entityPersisterMap.put( model.getEntityName(), cp ); - - if ( cp.getConcreteProxyClass() != null - && cp.getConcreteProxyClass().isInterface() - && !Map.class.isAssignableFrom( cp.getConcreteProxyClass() ) - && cp.getMappedClass() != cp.getConcreteProxyClass() ) { - // IMPL NOTE : we exclude Map based proxy interfaces here because that should - // indicate MAP entity mode.0 - - if ( cp.getMappedClass().equals( cp.getConcreteProxyClass() ) ) { - // this part handles an odd case in the Hibernate test suite where we map an interface - // as the class and the proxy. I cannot think of a real life use case for that - // specific test, but.. - log.debugf( - "Entity [%s] mapped same interface [%s] as class and proxy", - cp.getEntityName(), - cp.getMappedClass() - ); - } - else { - final String old = entityProxyInterfaceMap.put( cp.getConcreteProxyClass(), cp.getEntityName() ); - if ( old != null ) { - throw new HibernateException( - String.format( - Locale.ENGLISH, - "Multiple entities [%s, %s] named the same interface [%s] as their proxy which is not supported", - old, - cp.getEntityName(), - cp.getConcreteProxyClass().getName() - ) - ); - } - } - } - } - - for ( final Collection model : mappingMetadata.getCollectionBindings() ) { - final NavigableRole navigableRole = new NavigableRole( model.getRole() ); - - final CollectionDataAccess accessStrategy = sessionFactory.getCache().getCollectionRegionAccess( - navigableRole ); - - final CollectionPersister persister = persisterFactory.createCollectionPersister( - model, - accessStrategy, - persisterCreationContext - ); - collectionPersisterMap.put( model.getRole(), persister ); - Type indexType = persister.getIndexType(); - if ( indexType != null && indexType.isAssociationType() && !indexType.isAnyType() ) { - String entityName = ( (AssociationType) indexType ).getAssociatedEntityName( sessionFactory ); - Set roles = collectionRolesByEntityParticipant.get( entityName ); - if ( roles == null ) { - roles = new HashSet<>(); - collectionRolesByEntityParticipant.put( entityName, roles ); - } - roles.add( persister.getRole() ); - } - Type elementType = persister.getElementType(); - if ( elementType.isAssociationType() && !elementType.isAnyType() ) { - String entityName = ( (AssociationType) elementType ).getAssociatedEntityName( sessionFactory ); - Set roles = collectionRolesByEntityParticipant.get( entityName ); - if ( roles == null ) { - roles = new HashSet<>(); - collectionRolesByEntityParticipant.put( entityName, roles ); - } - roles.add( persister.getRole() ); - } - } - - // after *all* persisters and named queries are registered - entityPersisterMap.values().forEach( EntityPersister::generateEntityDefinition ); - - for ( EntityPersister persister : entityPersisterMap.values() ) { - persister.postInstantiate(); - registerEntityNameResolvers( persister, entityNameResolvers ); - } - collectionPersisterMap.values().forEach( CollectionPersister::postInstantiate ); - - jpaMetamodel.initialize( - this, - mappingMetadata, - sessionFactory.getQueryEngine().getCriteriaBuilder(), - jpaMetaModelPopulationSetting, - JpaStaticMetaModelPopulationSetting.determineJpaMetaModelPopulationSetting( sessionFactory.getProperties() ) - ); - } - - private void primeSecondLevelCacheRegions(MetadataImplementor mappingMetadata) { - final Map regionConfigBuilders = new ConcurrentHashMap<>(); - - // todo : ultimately this code can be made more efficient when we have a better intrinsic understanding of the hierarchy as a whole - - for ( PersistentClass bootEntityDescriptor : mappingMetadata.getEntityBindings() ) { - final AccessType accessType = AccessType.fromExternalName( bootEntityDescriptor.getCacheConcurrencyStrategy() ); - - if ( accessType != null ) { - if ( bootEntityDescriptor.isCached() ) { - regionConfigBuilders.computeIfAbsent( - bootEntityDescriptor.getRootClass().getCacheRegionName(), - DomainDataRegionConfigImpl.Builder::new - ) - .addEntityConfig( bootEntityDescriptor, accessType ); - } - - if ( RootClass.class.isInstance( bootEntityDescriptor ) - && bootEntityDescriptor.hasNaturalId() - && bootEntityDescriptor.getNaturalIdCacheRegionName() != null ) { - regionConfigBuilders.computeIfAbsent( - bootEntityDescriptor.getNaturalIdCacheRegionName(), - DomainDataRegionConfigImpl.Builder::new - ) - .addNaturalIdConfig( (RootClass) bootEntityDescriptor, accessType ); - } - } - } - - for ( Collection collection : mappingMetadata.getCollectionBindings() ) { - final AccessType accessType = AccessType.fromExternalName( collection.getCacheConcurrencyStrategy() ); - if ( accessType != null ) { - regionConfigBuilders.computeIfAbsent( - collection.getCacheRegionName(), - DomainDataRegionConfigImpl.Builder::new - ) - .addCollectionConfig( collection, accessType ); - } - } - - final Set regionConfigs; - if ( regionConfigBuilders.isEmpty() ) { - regionConfigs = Collections.emptySet(); - } - else { - regionConfigs = new HashSet<>(); - for ( DomainDataRegionConfigImpl.Builder builder : regionConfigBuilders.values() ) { - regionConfigs.add( builder.build() ); - } - } - - getSessionFactory().getCache().prime( regionConfigs ); - } - - @Override public java.util.Collection getEntityNameResolvers() { - return entityNameResolvers.keySet(); + return entityNameResolvers; } - private static void registerEntityNameResolvers( - EntityPersister persister, - Map entityNameResolvers) { - if ( persister.getEntityMetamodel() == null || persister.getEntityMetamodel().getTuplizer() == null ) { - return; - } - registerEntityNameResolvers( persister.getEntityMetamodel().getTuplizer(), entityNameResolvers ); - } - - private static void registerEntityNameResolvers( - EntityTuplizer tuplizer, - Map entityNameResolvers) { - EntityNameResolver[] resolvers = tuplizer.getEntityNameResolvers(); - if ( resolvers == null ) { - return; - } - - for ( EntityNameResolver resolver : resolvers ) { - entityNameResolvers.put( resolver, ENTITY_NAME_RESOLVER_MAP_VALUE ); - } - } - -// /** -// * Instantiate the metamodel. -// * -// * @param entityNameResolvers -// * @param entities The entity mappings. -// * @param embeddables The embeddable (component) mappings. -// * @param mappedSuperclassTypeMap The {@link javax.persistence.MappedSuperclass} mappings -// */ -// private MetamodelImpl( -// SessionFactoryImplementor sessionFactory, -// Map imports, -// Map entityPersisterMap, -// Map entityProxyInterfaceMap, -// ConcurrentHashMap entityNameResolvers, -// Map collectionPersisterMap, -// Map> collectionRolesByEntityParticipant, -// Map, EntityTypeImpl> entities, -// Map, EmbeddableTypeImpl> embeddables, -// Map, MappedSuperclassType> mappedSuperclassTypeMap, -// Map> entityTypesByEntityName) { -// this.sessionFactory = sessionFactory; -// this.imports = imports; -// this.entityPersisterMap = entityPersisterMap; -// this.entityProxyInterfaceMap = entityProxyInterfaceMap; -// this.entityNameResolvers = entityNameResolvers; -// this.collectionPersisterMap = collectionPersisterMap; -// this.collectionRolesByEntityParticipant = collectionRolesByEntityParticipant; -// this.entities = entities; -// this.embeddables = embeddables; -// this.mappedSuperclassTypeMap = mappedSuperclassTypeMap; -// this.entityTypesByEntityName = entityTypesByEntityName; -// } @Override public TypeConfiguration getTypeConfiguration() { @@ -404,16 +153,16 @@ public class DomainMetamodelImpl implements DomainMetamodel, MetamodelImplemento @Override public EntityPersister determineEntityPersister(Object entity) { - return findEntityDescriptor(entity.getClass()); + return findEntityDescriptor( entity.getClass() ); } @Override - public void visitEntityDescriptors(Consumer action){ + public void visitEntityDescriptors(Consumer action) { entityPersisterMap.values().forEach( action ); } @Override - public EntityPersister getEntityDescriptor(String entityName){ + public EntityPersister getEntityDescriptor(String entityName) { final EntityPersister entityPersister = entityPersisterMap.get( entityName ); if ( entityPersister == null ) { throw new IllegalArgumentException( "Unable to locate persister: " + entityName ); @@ -422,12 +171,12 @@ public class DomainMetamodelImpl implements DomainMetamodel, MetamodelImplemento } @Override - public EntityPersister findEntityDescriptor(String entityName){ + public EntityPersister findEntityDescriptor(String entityName) { return entityPersisterMap.get( entityName ); } @Override - public EntityPersister findEntityDescriptor(Class entityJavaType){ + public EntityPersister findEntityDescriptor(Class entityJavaType) { return findEntityDescriptor( entityJavaType.getName() ); } @@ -437,7 +186,7 @@ public class DomainMetamodelImpl implements DomainMetamodel, MetamodelImplemento } @Override - public EntityPersister getEntityDescriptor(Class entityJavaType){ + public EntityPersister getEntityDescriptor(Class entityJavaType) { EntityPersister entityPersister = entityPersisterMap.get( entityJavaType.getName() ); if ( entityPersister == null ) { String mappedEntityName = entityProxyInterfaceMap.get( entityJavaType ); @@ -454,7 +203,7 @@ public class DomainMetamodelImpl implements DomainMetamodel, MetamodelImplemento } @Override - public EntityPersister locateEntityDescriptor(Class byClass){ + public EntityPersister locateEntityDescriptor(Class byClass) { EntityPersister entityPersister = entityPersisterMap.get( byClass.getName() ); if ( entityPersister == null ) { String mappedEntityName = entityProxyInterfaceMap.get( byClass ); @@ -579,21 +328,21 @@ public class DomainMetamodelImpl implements DomainMetamodel, MetamodelImplemento } @Override - public void visitCollectionDescriptors(Consumer action){ + public void visitCollectionDescriptors(Consumer action) { collectionPersisterMap.values().forEach( action ); } @Override - public CollectionPersister getCollectionDescriptor(String role){ + public CollectionPersister getCollectionDescriptor(String role) { CollectionPersister collectionPersister = collectionPersisterMap.get( role ); - if(collectionPersister == null){ + if ( collectionPersister == null ) { throw new IllegalArgumentException( "Unable to locate persister: " + role ); } return collectionPersister; } @Override - public CollectionPersister findCollectionDescriptor(String role){ + public CollectionPersister findCollectionDescriptor(String role) { return collectionPersisterMap.get( role ); } @@ -635,7 +384,7 @@ public class DomainMetamodelImpl implements DomainMetamodel, MetamodelImplemento } @Override - public RootGraph findNamedGraph(String name){ + public RootGraph findNamedGraph(String name) { return findEntityGraphByName( name ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java index 4d497ac497..4497ea9f9e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java @@ -28,7 +28,7 @@ public class EmbeddableTypeImpl implements EmbeddableDomainType, Serializable { public EmbeddableTypeImpl(JavaTypeDescriptor javaTypeDescriptor, NodeBuilder nodeBuilder) { - super( javaTypeDescriptor.getJavaType().getName(), javaTypeDescriptor, null, nodeBuilder.getDomainModel() ); + super( javaTypeDescriptor.getJavaType().getName(), javaTypeDescriptor, null ); } public EmbeddableTypeImpl( @@ -37,9 +37,11 @@ public class EmbeddableTypeImpl //noinspection unchecked super( name, - (JavaTypeDescriptor) nodeBuilder.getDomainModel().getTypeConfiguration().getJavaTypeDescriptorRegistry().getDescriptor( Map.class ), - null, - nodeBuilder.getDomainModel() + (JavaTypeDescriptor) nodeBuilder.getDomainModel() + .getTypeConfiguration() + .getJavaTypeDescriptorRegistry() + .getDescriptor( Map.class ), + null ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntityTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntityTypeImpl.java index 9488bfe20b..de5711b657 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntityTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntityTypeImpl.java @@ -36,16 +36,14 @@ public class EntityTypeImpl public EntityTypeImpl( JavaTypeDescriptor javaTypeDescriptor, IdentifiableDomainType superType, - PersistentClass persistentClass, - JpaMetamodel jpaMetamodel) { + PersistentClass persistentClass) { super( persistentClass.getEntityName(), javaTypeDescriptor, superType, persistentClass.getDeclaredIdentifierMapper() != null || ( superType != null && superType.hasIdClass() ), persistentClass.hasIdentifierProperty(), - persistentClass.isVersioned(), - jpaMetamodel + persistentClass.isVersioned() ); this.jpaEntityName = persistentClass.getJpaEntityName(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java index 7584ad638e..659679a506 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java @@ -12,9 +12,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArraySet; import java.util.function.Consumer; - import javax.persistence.EntityGraph; import javax.persistence.NamedAttributeNode; import javax.persistence.NamedEntityGraph; @@ -23,11 +21,9 @@ import javax.persistence.metamodel.Attribute; import javax.persistence.metamodel.EmbeddableType; import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.ManagedType; -import javax.persistence.metamodel.MappedSuperclassType; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; -import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.cfg.annotations.NamedEntityGraphDefinition; import org.hibernate.graph.internal.RootGraphImpl; import org.hibernate.graph.spi.AttributeNodeImplementor; @@ -38,20 +34,14 @@ import org.hibernate.internal.EntityManagerMessageLogger; import org.hibernate.internal.HEMLogging; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.CollectionHelper; -import org.hibernate.mapping.MappedSuperclass; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.internal.JpaMetaModelPopulationSetting; -import org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting; +import org.hibernate.metamodel.internal.InflightRuntimeMetamodel; +import org.hibernate.metamodel.model.domain.AbstractDomainType; import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType; -import org.hibernate.metamodel.model.domain.IdentifiableDomainType; import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType; -import org.hibernate.metamodel.spi.DomainMetamodel; -import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder; import org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor; -import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.spi.TypeConfiguration; /** @@ -63,57 +53,233 @@ public class JpaMetamodelImpl implements JpaMetamodel { private final TypeConfiguration typeConfiguration; - private final Map> entityDescriptorMap = new ConcurrentHashMap<>(); - private final Map> strictEntityDescriptorMap = new ConcurrentHashMap<>(); + private final Map> entityDescriptorMap; - private final Map, MappedSuperclassType> mappedSuperclassTypeMap = new ConcurrentHashMap<>(); + private final Map, MappedSuperclassDomainType> mappedSuperclassTypeMap; - private final Map> embeddableDescriptorMap = new ConcurrentHashMap<>(); + private final Map> embeddableDescriptorMap; - private final Map nameToImportNameMap = new ConcurrentHashMap<>(); + private final Map nameToImportNameMap; private final transient Map entityGraphMap = new ConcurrentHashMap<>(); private final Map> polymorphicEntityReferenceMap = new ConcurrentHashMap<>(); - public JpaMetamodelImpl(TypeConfiguration typeConfiguration) { - this.typeConfiguration = typeConfiguration; + private final Map entityProxyInterfaceMap; + + + public JpaMetamodelImpl( + InflightRuntimeMetamodel runtimeMetamodel, + java.util.Collection namedEntityGraphDefinitions) { + this.typeConfiguration = runtimeMetamodel.getTypeConfiguration(); + + entityDescriptorMap = runtimeMetamodel.getJpaEntityTypeMap(); + mappedSuperclassTypeMap = runtimeMetamodel.getJpaMappedSuperclassTypeMap(); + embeddableDescriptorMap = runtimeMetamodel.getJpaEmbeddableDescriptorMap(); + + entityDescriptorMap.values() + .forEach( domainType -> ( (AbstractDomainType) domainType ).injectJpaMetamodel( this ) ); + mappedSuperclassTypeMap.values().forEach( domainType -> ( (AbstractDomainType) domainType ).injectJpaMetamodel( + this ) ); + entityDescriptorMap.values() + .forEach( domainType -> ( (AbstractDomainType) domainType ).injectJpaMetamodel( this ) ); + + nameToImportNameMap = runtimeMetamodel.getNameToImportNameMap(); + entityProxyInterfaceMap = runtimeMetamodel.getEntityProxyInterfaceMap(); + applyNamedEntityGraphs( namedEntityGraphDefinitions ); } - public void initialize( - DomainMetamodel metamodel, - MetadataImplementor mappingMetadata, - SqmCriteriaNodeBuilder criteriaBuilder, - JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting, - JpaStaticMetaModelPopulationSetting jpaStaticMetaModelPopulationSetting) { - if ( jpaMetaModelPopulationSetting != JpaMetaModelPopulationSetting.DISABLED ) { - MetadataContext context = new MetadataContext( - metamodel, - criteriaBuilder, - mappingMetadata.getMappedSuperclassMappingsCopy(), - typeConfiguration, - jpaMetaModelPopulationSetting, - jpaStaticMetaModelPopulationSetting - ); + @Override + public TypeConfiguration getTypeConfiguration() { + return typeConfiguration; + } - for ( PersistentClass entityBinding : mappingMetadata.getEntityBindings() ) { - locateOrBuildEntityType( entityBinding, context ); - } - handleUnusedMappedSuperclasses( context ); + @Override + public EntityDomainType entity(String entityName) { + //noinspection unchecked + return (EntityDomainType) entityDescriptorMap.get( entityName ); + } - context.wrapUp(); + @Override + public EntityDomainType resolveHqlEntityReference(String entityName) { + final String rename = resolveImportedName( entityName ); + if ( rename != null ) { + entityName = rename; + } - this.nameToImportNameMap.putAll( mappingMetadata.getImports() ); + final EntityDomainType entityDescriptor = entity( entityName ); + if ( entityDescriptor != null ) { + return entityDescriptor; + } - this.strictEntityDescriptorMap.putAll( context.getEntityTypeMap() ); - this.entityDescriptorMap.putAll( context.getEntityTypesByEntityName() ); - this.mappedSuperclassTypeMap.putAll( context.getMappedSuperclassTypeMap() ); + final Class requestedClass = resolveRequestedClass( entityName ); + if ( requestedClass != null ) { + return resolveEntityReference( requestedClass ); + } - for ( EmbeddableDomainType embeddable : context.getEmbeddableTypeSet() ) { - this.embeddableDescriptorMap.put( embeddable.getJavaType(), embeddable ); + throw new IllegalArgumentException( "Could not resolve entity reference " + entityName ); + } + + @Override + @SuppressWarnings("unchecked") + public void visitManagedTypes(Consumer> action) { + visitEntityTypes( (Consumer) action ); + visitEmbeddables( (Consumer) action ); + mappedSuperclassTypeMap.values().forEach( (Consumer) action ); + } + + @Override + public void visitEntityTypes(Consumer> action) { + entityDescriptorMap.values().forEach( action ); + } + + @Override + public void visitRootEntityTypes(Consumer> action) { + entityDescriptorMap.values().forEach( + entityDomainType -> { + if ( entityDomainType.getSuperType() == null ) { + action.accept( entityDomainType ); + } + } + ); + } + + @Override + public void visitEmbeddables(Consumer> action) { + embeddableDescriptorMap.values().forEach( action ); + } + + @Override + public ManagedDomainType managedType(Class cls) { + ManagedType type = entityDescriptorMap.get( cls ); + if ( type == null ) { + type = mappedSuperclassTypeMap.get( cls ); + } + if ( type == null ) { + type = embeddableDescriptorMap.get( cls ); + } + if ( type == null ) { + // per JPA + throw new IllegalArgumentException( "Not a managed type: " + cls ); + } + + //noinspection unchecked + return (ManagedDomainType) type; + } + + @Override + public EntityDomainType entity(Class cls) { + final EntityType entityType = entityDescriptorMap.get( cls ); + if ( entityType == null ) { + throw new IllegalArgumentException( "Not an entity: " + cls ); + } + //noinspection unchecked + return (EntityDomainType) entityType; + } + + @Override + public EmbeddableDomainType embeddable(Class cls) { + final EmbeddableDomainType embeddableType = embeddableDescriptorMap.get( cls ); + if ( embeddableType == null ) { + throw new IllegalArgumentException( "Not an embeddable: " + cls ); + } + //noinspection unchecked + return (EmbeddableDomainType) embeddableType; + } + + @Override + public Set> getManagedTypes() { + final int setSize = CollectionHelper.determineProperSizing( + entityDescriptorMap.size() + mappedSuperclassTypeMap.size() + embeddableDescriptorMap.size() + ); + final Set> managedTypes = new HashSet<>( setSize ); + managedTypes.addAll( entityDescriptorMap.values() ); + managedTypes.addAll( mappedSuperclassTypeMap.values() ); + managedTypes.addAll( embeddableDescriptorMap.values() ); + return managedTypes; + } + + @Override + public Set> getEntities() { + return new HashSet<>( entityDescriptorMap.values() ); + } + + @Override + public Set> getEmbeddables() { + return new HashSet<>( embeddableDescriptorMap.values() ); + } + + @Override + public void addNamedEntityGraph(String graphName, RootGraphImplementor entityGraph) { + final EntityGraph old = entityGraphMap.put( + graphName, + entityGraph.makeImmutableCopy( graphName ) + ); + + if ( old != null ) { + log.debugf( "EntityGraph being replaced on EntityManagerFactory for name %s", graphName ); + } + } + + @Override + public RootGraphImplementor findEntityGraphByName(String name) { + //noinspection unchecked + return entityGraphMap.get( name ); + } + + @Override + public List> findEntityGraphsByJavaType(Class entityClass) { + final EntityDomainType entityType = entity( entityClass ); + if ( entityType == null ) { + throw new IllegalArgumentException( "Given class is not an entity : " + entityClass.getName() ); + } + + final List> results = new ArrayList<>(); + + for ( EntityGraph entityGraph : entityGraphMap.values() ) { + if ( !( entityGraph instanceof RootGraphImplementor ) ) { + continue; } - applyNamedEntityGraphs( mappingMetadata.getNamedEntityGraphs().values() ); + final RootGraphImplementor egi = (RootGraphImplementor) entityGraph; + //noinspection unchecked + if ( egi.appliesTo( entityType ) ) { + //noinspection unchecked + results.add( egi ); + } + } + + return results; + } + + private String resolveImportedName(String name) { + String result = nameToImportNameMap.get( name ); + if ( result == null ) { + // see if the name is a fully-qualified class name + try { + getServiceRegistry().getService( ClassLoaderService.class ).classForName( name ); + + // it is a fully-qualified class name - add it to the cache + // so we do not keep trying later + nameToImportNameMap.put( name, name ); + return name; + } + catch (ClassLoadingException cnfe) { + // it is a NOT fully-qualified class name - add a marker entry + // so we do not keep trying later + nameToImportNameMap.put( name, INVALID_IMPORT ); + return null; + } + } + else { + // explicitly check for same instance + //noinspection StringEquality + if ( result == INVALID_IMPORT ) { + return null; + } + else { + return result; + } } } @@ -199,292 +365,6 @@ public class JpaMetamodelImpl implements JpaMetamodel { } } - private static void handleUnusedMappedSuperclasses(MetadataContext context) { - final Set unusedMappedSuperclasses = context.getUnusedMappedSuperclasses(); - if ( !unusedMappedSuperclasses.isEmpty() ) { - for ( MappedSuperclass mappedSuperclass : unusedMappedSuperclasses ) { - log.unusedMappedSuperclass( mappedSuperclass.getMappedClass().getName() ); - locateOrBuildMappedSuperclassType( mappedSuperclass, context ); - } - } - } - - private static MappedSuperclassDomainType locateOrBuildMappedSuperclassType( - MappedSuperclass mappedSuperclass, MetadataContext context) { - MappedSuperclassDomainType mappedSuperclassType = context.locateMappedSuperclassType( mappedSuperclass ); - if ( mappedSuperclassType == null ) { - mappedSuperclassType = buildMappedSuperclassType( mappedSuperclass, context ); - } - return mappedSuperclassType; - } - - //TODO remove / reduce @SW scope - @SuppressWarnings("unchecked") - private static MappedSuperclassTypeImpl buildMappedSuperclassType( - MappedSuperclass mappedSuperclass, - MetadataContext context) { - final MappedSuperclass superMappedSuperclass = mappedSuperclass.getSuperMappedSuperclass(); - IdentifiableDomainType superType = superMappedSuperclass == null - ? null - : locateOrBuildMappedSuperclassType( superMappedSuperclass, context ); - //no mappedSuperclass, check for a super entity - if ( superType == null ) { - final PersistentClass superPersistentClass = mappedSuperclass.getSuperPersistentClass(); - superType = superPersistentClass == null - ? null - : locateOrBuildEntityType( superPersistentClass, context ); - } - final JavaTypeDescriptor javaTypeDescriptor = context.getTypeConfiguration() - .getJavaTypeDescriptorRegistry() - .getDescriptor( mappedSuperclass.getMappedClass() ); - MappedSuperclassTypeImpl mappedSuperclassType = new MappedSuperclassTypeImpl( - javaTypeDescriptor, - mappedSuperclass, - superType, - context.getMetamodel().getJpaMetamodel() - ); - context.registerMappedSuperclassType( mappedSuperclass, mappedSuperclassType ); - return mappedSuperclassType; - } - - - private static EntityDomainType locateOrBuildEntityType( - PersistentClass persistentClass, - MetadataContext context) { - EntityDomainType entityType = context.locateEntityType( persistentClass ); - if ( entityType == null ) { - entityType = buildEntityType( persistentClass, context ); - } - return entityType; - } - - //TODO remove / reduce @SW scope - @SuppressWarnings("unchecked") - private static EntityTypeImpl buildEntityType(PersistentClass persistentClass, MetadataContext context) { - final Class javaType = persistentClass.getMappedClass(); - context.pushEntityWorkedOn( persistentClass ); - final MappedSuperclass superMappedSuperclass = persistentClass.getSuperMappedSuperclass(); - IdentifiableDomainType superType = superMappedSuperclass == null - ? null - : locateOrBuildMappedSuperclassType( superMappedSuperclass, context ); - //no mappedSuperclass, check for a super entity - if ( superType == null ) { - final PersistentClass superPersistentClass = persistentClass.getSuperclass(); - superType = superPersistentClass == null - ? null - : locateOrBuildEntityType( superPersistentClass, context ); - } - - final JavaTypeDescriptor javaTypeDescriptor = context.getTypeConfiguration() - .getJavaTypeDescriptorRegistry() - .getDescriptor( javaType ); - EntityTypeImpl entityType = new EntityTypeImpl( - javaTypeDescriptor, - superType, - persistentClass, - context.getMetamodel().getJpaMetamodel() - ); - - context.registerEntityType( persistentClass, entityType ); - context.popEntityWorkedOn( persistentClass ); - return entityType; - } - - - @Override - public TypeConfiguration getTypeConfiguration() { - return typeConfiguration; - } - - @Override - public EntityDomainType entity(String entityName) { - //noinspection unchecked - return (EntityDomainType) entityDescriptorMap.get( entityName ); - } - - @Override - public EntityDomainType resolveHqlEntityReference(String entityName) { - final String rename = resolveImportedName( entityName ); - if ( rename != null ) { - entityName = rename; - } - - final EntityDomainType entityDescriptor = entity( entityName ); - if ( entityDescriptor != null ) { - return entityDescriptor; - } - - final Class requestedClass = resolveRequestedClass( entityName ); - if ( requestedClass != null ) { - return resolveEntityReference( requestedClass ); - } - - throw new IllegalArgumentException( "Could not resolve entity reference " + entityName ); - } - - @Override - @SuppressWarnings("unchecked") - public void visitManagedTypes(Consumer> action) { - visitEntityTypes( (Consumer) action ); - visitEmbeddables( (Consumer) action ); - mappedSuperclassTypeMap.values().forEach( (Consumer) action ); - } - - @Override - public void visitEntityTypes(Consumer> action) { - entityDescriptorMap.values().forEach( action ); - } - - @Override - public void visitRootEntityTypes(Consumer> action) { - entityDescriptorMap.values().forEach( - entityDomainType -> { - if ( entityDomainType.getSuperType() == null ) { - action.accept( entityDomainType ); - } - } - ); - } - - @Override - public void visitEmbeddables(Consumer> action) { - embeddableDescriptorMap.values().forEach( action ); - } - - @Override - public ManagedDomainType managedType(Class cls) { - ManagedType type = strictEntityDescriptorMap.get( cls ); - if ( type == null ) { - type = mappedSuperclassTypeMap.get( cls ); - } - if ( type == null ) { - type = embeddableDescriptorMap.get( cls ); - } - if ( type == null ) { - // per JPA - throw new IllegalArgumentException( "Not a managed type: " + cls ); - } - - //noinspection unchecked - return (ManagedDomainType) type; - } - - @Override - public EntityDomainType entity(Class cls) { - final EntityType entityType = strictEntityDescriptorMap.get( cls ); - if ( entityType == null ) { - throw new IllegalArgumentException( "Not an entity: " + cls ); - } - //noinspection unchecked - return (EntityDomainType) entityType; - } - - @Override - public EmbeddableDomainType embeddable(Class cls) { - final EmbeddableDomainType embeddableType = embeddableDescriptorMap.get( cls ); - if ( embeddableType == null ) { - throw new IllegalArgumentException( "Not an embeddable: " + cls ); - } - //noinspection unchecked - return (EmbeddableDomainType) embeddableType; - } - - @Override - public Set> getManagedTypes() { - final int setSize = CollectionHelper.determineProperSizing( - entityDescriptorMap.size() + mappedSuperclassTypeMap.size() + embeddableDescriptorMap.size() - ); - final Set> managedTypes = new HashSet<>( setSize ); - managedTypes.addAll( entityDescriptorMap.values() ); - managedTypes.addAll( mappedSuperclassTypeMap.values() ); - managedTypes.addAll( embeddableDescriptorMap.values() ); - return managedTypes; - } - - @Override - public Set> getEntities() { - return new HashSet<>( entityDescriptorMap.values() ); - } - - @Override - public Set> getEmbeddables() { - return new HashSet<>( embeddableDescriptorMap.values() ); - } - - @Override - public void addNamedEntityGraph(String graphName, RootGraphImplementor entityGraph) { - final EntityGraph old = entityGraphMap.put( - graphName, - entityGraph.makeImmutableCopy( graphName ) - ); - - if ( old != null ) { - log.debugf( "EntityGraph being replaced on EntityManagerFactory for name %s", graphName ); - } - } - - @Override - public RootGraphImplementor findEntityGraphByName(String name) { - //noinspection unchecked - return entityGraphMap.get( name ); - } - - @Override - public List> findEntityGraphsByJavaType(Class entityClass) { - final EntityDomainType entityType = entity( entityClass ); - if ( entityType == null ) { - throw new IllegalArgumentException( "Given class is not an entity : " + entityClass.getName() ); - } - - final List> results = new ArrayList<>(); - - for ( EntityGraph entityGraph : entityGraphMap.values() ) { - if ( !(entityGraph instanceof RootGraphImplementor) ) { - continue; - } - - final RootGraphImplementor egi = (RootGraphImplementor) entityGraph; - //noinspection unchecked - if ( egi.appliesTo( entityType ) ) { - //noinspection unchecked - results.add( egi ); - } - } - - return results; - } - - private String resolveImportedName(String name) { - String result = nameToImportNameMap.get( name ); - if ( result == null ) { - // see if the name is a fully-qualified class name - try { - getServiceRegistry().getService( ClassLoaderService.class ).classForName( name ); - - // it is a fully-qualified class name - add it to the cache - // so we do not keep trying later - nameToImportNameMap.put( name, name ); - return name; - } - catch (ClassLoadingException cnfe) { - // it is a NOT fully-qualified class name - add a marker entry - // so we do not keep trying later - nameToImportNameMap.put( name, INVALID_IMPORT ); - return null; - } - } - else { - // explicitly check for same instance - //noinspection StringEquality - if ( result == INVALID_IMPORT ) { - return null; - } - else { - return result; - } - } - } - private Class resolveRequestedClass(String entityName) { try { return getServiceRegistry().getService( ClassLoaderService.class ).classForName( entityName ); @@ -498,7 +378,7 @@ public class JpaMetamodelImpl implements JpaMetamodel { public EntityDomainType resolveEntityReference(Class javaType) { // try the incoming Java type as a "strict" entity reference { - final EntityDomainType descriptor = strictEntityDescriptorMap.get( javaType ); + final EntityDomainType descriptor = entityDescriptorMap.get( javaType ); if ( descriptor != null ) { return (EntityDomainType) descriptor; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappedSuperclassTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappedSuperclassTypeImpl.java index 9df376c85f..594a8a0f1e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappedSuperclassTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappedSuperclassTypeImpl.java @@ -11,7 +11,6 @@ import org.hibernate.graph.spi.SubGraphImplementor; import org.hibernate.mapping.MappedSuperclass; import org.hibernate.metamodel.model.domain.AbstractIdentifiableType; import org.hibernate.metamodel.model.domain.IdentifiableDomainType; -import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType; import org.hibernate.type.descriptor.java.JavaTypeDescriptor; @@ -23,16 +22,14 @@ public class MappedSuperclassTypeImpl extends AbstractIdentifiableType imp public MappedSuperclassTypeImpl( JavaTypeDescriptor javaTypeDescriptor, MappedSuperclass mappedSuperclass, - IdentifiableDomainType superType, - JpaMetamodel jpaMetamodel) { + IdentifiableDomainType superType) { super( javaTypeDescriptor.getJavaType().getName(), javaTypeDescriptor, superType, mappedSuperclass.getDeclaredIdentifierMapper() != null || ( superType != null && superType.hasIdClass() ), mappedSuperclass.hasIdentifierProperty(), - mappedSuperclass.isVersioned(), - jpaMetamodel + mappedSuperclass.isVersioned() ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/AssociationType.java b/hibernate-core/src/main/java/org/hibernate/type/AssociationType.java index 9ff06e14c7..e40206bcfa 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/AssociationType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/AssociationType.java @@ -23,7 +23,7 @@ public interface AssociationType extends Type { /** * Get the foreign key directionality of this association */ - public ForeignKeyDirection getForeignKeyDirection(); + ForeignKeyDirection getForeignKeyDirection(); //TODO: move these to a new JoinableType abstract class, //extended by EntityType and PersistentCollectionType: @@ -32,47 +32,47 @@ public interface AssociationType extends Type { * Is the primary key of the owning entity table * to be used in the join? */ - public boolean useLHSPrimaryKey(); + boolean useLHSPrimaryKey(); /** * Get the name of a property in the owning entity * that provides the join key (null if the identifier) */ - public String getLHSPropertyName(); + String getLHSPropertyName(); /** * The name of a unique property of the associated entity * that provides the join key (null if the identifier of * an entity, or key of a collection) */ - public String getRHSUniqueKeyPropertyName(); + String getRHSUniqueKeyPropertyName(); /** * Get the "persister" for this association - a class or * collection persister */ - public Joinable getAssociatedJoinable(SessionFactoryImplementor factory) throws MappingException; + Joinable getAssociatedJoinable(SessionFactoryImplementor factory) throws MappingException; /** * Get the entity name of the associated entity */ - public String getAssociatedEntityName(SessionFactoryImplementor factory) throws MappingException; - + String getAssociatedEntityName(SessionFactoryImplementor factory) throws MappingException; + /** * Get the "filtering" SQL fragment that is applied in the * SQL on clause, in addition to the usual join condition */ - public String getOnCondition(String alias, SessionFactoryImplementor factory, Map enabledFilters) + String getOnCondition(String alias, SessionFactoryImplementor factory, Map enabledFilters) throws MappingException; /** * Get the "filtering" SQL fragment that is applied in the * SQL on clause, in addition to the usual join condition */ - public String getOnCondition(String alias, SessionFactoryImplementor factory, Map enabledFilters, Set treatAsDeclarations); + String getOnCondition(String alias, SessionFactoryImplementor factory, Map enabledFilters, Set treatAsDeclarations); /** * Do we dirty check this association, even when there are * no columns to be updated? */ - public abstract boolean isAlwaysDirtyChecked(); + boolean isAlwaysDirtyChecked(); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/spi/TypeConfiguration.java b/hibernate-core/src/main/java/org/hibernate/type/spi/TypeConfiguration.java index 2051eb8911..da3f733c56 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/spi/TypeConfiguration.java +++ b/hibernate-core/src/main/java/org/hibernate/type/spi/TypeConfiguration.java @@ -184,7 +184,7 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable { scope.setSessionFactory( sessionFactory ); sessionFactory.addObserver( this ); - return new DomainMetamodelImpl( sessionFactory, this ); + return new DomainMetamodelImpl( sessionFactory, this, this.jpaMetamodel ); } /** diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/metadata/MetadataTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/metadata/MetadataTest.java index fa94dbbf26..b7e9d5f165 100644 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/metadata/MetadataTest.java +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/metadata/MetadataTest.java @@ -94,7 +94,9 @@ public class MetadataTest extends BaseEntityManagerFunctionalTestCase { .addAnnotatedClass( WithGenericCollection.class ) .buildMetadata(); SessionFactoryImplementor sfi = (SessionFactoryImplementor) metadata.buildSessionFactory(); - DomainMetamodelImpl metamodel = new DomainMetamodelImpl( sfi, ( (MetadataImplementor) metadata ).getTypeConfiguration() ); + DomainMetamodelImpl metamodel = new DomainMetamodelImpl( sfi, ( (MetadataImplementor) metadata ).getTypeConfiguration(), + this.jpaMetamodel + ); metamodel.initialize( (MetadataImplementor) metadata, JpaMetaModelPopulationSetting.IGNORE_UNSUPPORTED ); sfi.close(); }