6 - SQM based on JPA type system, RuntimeModelCreationProcess
This commit is contained in:
parent
f52e305ffb
commit
f20d36be40
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.model.domain.internal;
|
package org.hibernate.metamodel.internal;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Member;
|
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.PluralPersistentAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.SimpleDomainType;
|
import org.hibernate.metamodel.model.domain.SimpleDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
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.internal.PropertyAccessMapImpl;
|
||||||
import org.hibernate.property.access.spi.Getter;
|
import org.hibernate.property.access.spi.Getter;
|
||||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||||
|
@ -293,9 +298,8 @@ public class AttributeFactory {
|
||||||
private EntityMetamodel getDeclarerEntityMetamodel(AbstractIdentifiableType<?> ownerType) {
|
private EntityMetamodel getDeclarerEntityMetamodel(AbstractIdentifiableType<?> ownerType) {
|
||||||
final Type.PersistenceType persistenceType = ownerType.getPersistenceType();
|
final Type.PersistenceType persistenceType = ownerType.getPersistenceType();
|
||||||
if ( persistenceType == Type.PersistenceType.ENTITY ) {
|
if ( persistenceType == Type.PersistenceType.ENTITY ) {
|
||||||
return context.getSessionFactory()
|
return context.getMetamodel()
|
||||||
.getMetamodel()
|
.getEntityDescriptor( ownerType.getTypeName() )
|
||||||
.entityPersister( ownerType.getTypeName() )
|
|
||||||
.getEntityMetamodel();
|
.getEntityMetamodel();
|
||||||
}
|
}
|
||||||
else if ( persistenceType == Type.PersistenceType.MAPPED_SUPERCLASS ) {
|
else if ( persistenceType == Type.PersistenceType.MAPPED_SUPERCLASS ) {
|
|
@ -7,21 +7,48 @@
|
||||||
package org.hibernate.metamodel.internal;
|
package org.hibernate.metamodel.internal;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
import org.hibernate.EntityNameResolver;
|
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.EmbeddableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
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.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.collection.CollectionPersister;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
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;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class InflightRuntimeMetamodel {
|
public class InflightRuntimeMetamodel {
|
||||||
|
private static final EntityManagerMessageLogger log = HEMLogging.messageLogger( InflightRuntimeMetamodel.class );
|
||||||
|
|
||||||
private final TypeConfiguration typeConfiguration;
|
private final TypeConfiguration typeConfiguration;
|
||||||
|
|
||||||
|
@ -29,28 +56,372 @@ public class InflightRuntimeMetamodel {
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Hibernate metamodel
|
// Hibernate metamodel
|
||||||
|
|
||||||
private final Map<String, EntityPersister> entityPersisterMap = new HashMap<>();
|
private final Map<String, EntityPersister> entityPersisterMap = new ConcurrentHashMap<>();
|
||||||
private Map<Class, String> entityProxyInterfaceMap;
|
private final Map<Class, String> entityProxyInterfaceMap = new ConcurrentHashMap<>();
|
||||||
private Map<String, CollectionPersister> collectionPersisterMap;
|
private final Map<String, CollectionPersister> collectionPersisterMap = new ConcurrentHashMap<>();
|
||||||
private Map<String, Set<String>> collectionRolesByEntityParticipant;
|
private final Map<String, Set<String>> collectionRolesByEntityParticipant = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// JPA metamodel
|
// JPA metamodel
|
||||||
|
|
||||||
private final Map<String, EntityDomainType<?>> jpaEntityTypeMap = new HashMap<>();
|
private final Map<String, EntityDomainType<?>> jpaEntityTypeMap = new ConcurrentHashMap<>();
|
||||||
private Map<Class, MappedSuperclassDomainType<?>> jpaMappedSuperclassTypeMap;
|
private final Map<Class<?>, MappedSuperclassDomainType<?>> jpaMappedSuperclassTypeMap = new ConcurrentHashMap<>();
|
||||||
private Map<Class, EmbeddableDomainType<?>> embeddableDescriptorMap;
|
private Map<Class, EmbeddableDomainType<?>> jpaEmbeddableDescriptorMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Misc
|
// Misc
|
||||||
|
|
||||||
private final Map<String, String> nameToImportNameMap = new HashMap<>();
|
private final Map<String, String> nameToImportNameMap = new HashMap<>();
|
||||||
private Set<EntityNameResolver> entityNameResolvers;
|
private final Set<EntityNameResolver> entityNameResolvers = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
|
|
||||||
public InflightRuntimeMetamodel(TypeConfiguration typeConfiguration) {
|
public InflightRuntimeMetamodel(TypeConfiguration typeConfiguration) {
|
||||||
this.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<String, EntityPersister> getEntityPersisterMap() {
|
||||||
|
return entityPersisterMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Class, String> getEntityProxyInterfaceMap() {
|
||||||
|
return entityProxyInterfaceMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, CollectionPersister> getCollectionPersisterMap() {
|
||||||
|
return collectionPersisterMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Set<String>> getCollectionRolesByEntityParticipant() {
|
||||||
|
return collectionRolesByEntityParticipant;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, EntityDomainType<?>> getJpaEntityTypeMap() {
|
||||||
|
return jpaEntityTypeMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Class<?>, MappedSuperclassDomainType<?>> getJpaMappedSuperclassTypeMap() {
|
||||||
|
return jpaMappedSuperclassTypeMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Class, EmbeddableDomainType<?>> getJpaEmbeddableDescriptorMap() {
|
||||||
|
return jpaEmbeddableDescriptorMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getNameToImportNameMap() {
|
||||||
|
return nameToImportNameMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<EntityNameResolver> 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<PersistentClass> 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<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<String> 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<String> 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<EntityNameResolver> entityNameResolvers) {
|
||||||
|
if ( persister.getEntityMetamodel() == null || persister.getEntityMetamodel().getTuplizer() == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
registerEntityNameResolvers( persister.getEntityMetamodel().getTuplizer(), entityNameResolvers );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void registerEntityNameResolvers(
|
||||||
|
EntityTuplizer tuplizer,
|
||||||
|
Set<EntityNameResolver> entityNameResolvers) {
|
||||||
|
EntityNameResolver[] resolvers = tuplizer.getEntityNameResolvers();
|
||||||
|
if ( resolvers == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( EntityNameResolver resolver : resolvers ) {
|
||||||
|
entityNameResolvers.add( resolver );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void handleUnusedMappedSuperclasses(MetadataContext context) {
|
||||||
|
final Set<MappedSuperclass> 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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.model.domain.internal;
|
package org.hibernate.metamodel.internal;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -17,13 +17,10 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.persistence.metamodel.Attribute;
|
import javax.persistence.metamodel.Attribute;
|
||||||
import javax.persistence.metamodel.IdentifiableType;
|
import javax.persistence.metamodel.IdentifiableType;
|
||||||
import javax.persistence.metamodel.MappedSuperclassType;
|
|
||||||
import javax.persistence.metamodel.Metamodel;
|
|
||||||
import javax.persistence.metamodel.SingularAttribute;
|
import javax.persistence.metamodel.SingularAttribute;
|
||||||
import javax.persistence.metamodel.Type;
|
import javax.persistence.metamodel.Type;
|
||||||
|
|
||||||
import org.hibernate.annotations.common.AssertionFailure;
|
import org.hibernate.annotations.common.AssertionFailure;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|
||||||
import org.hibernate.internal.EntityManagerMessageLogger;
|
import org.hibernate.internal.EntityManagerMessageLogger;
|
||||||
import org.hibernate.internal.HEMLogging;
|
import org.hibernate.internal.HEMLogging;
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
import org.hibernate.internal.util.ReflectHelper;
|
||||||
|
@ -33,20 +30,20 @@ import org.hibernate.mapping.KeyValue;
|
||||||
import org.hibernate.mapping.MappedSuperclass;
|
import org.hibernate.mapping.MappedSuperclass;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.Property;
|
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.AbstractIdentifiableType;
|
||||||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
|
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.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType;
|
import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||||
import org.hibernate.metamodel.spi.DomainMetamodel;
|
import org.hibernate.metamodel.model.domain.internal.AttributeContainer;
|
||||||
import org.hibernate.metamodel.spi.MetamodelImplementor;
|
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.query.sqm.internal.SqmCriteriaNodeBuilder;
|
||||||
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
|
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
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.
|
* Stack of PersistentClass being process. Last in the list is the highest in the stack.
|
||||||
*/
|
*/
|
||||||
private List<PersistentClass> stackOfPersistentClassesBeingProcessed = new ArrayList<>();
|
private List<PersistentClass> stackOfPersistentClassesBeingProcessed = new ArrayList<>();
|
||||||
private DomainMetamodel metamodel;
|
private InflightRuntimeMetamodel metamodel;
|
||||||
|
|
||||||
public MetadataContext(
|
public MetadataContext(
|
||||||
DomainMetamodel metamodel,
|
InflightRuntimeMetamodel metamodel,
|
||||||
SqmCriteriaNodeBuilder criteriaBuilder,
|
SqmCriteriaNodeBuilder criteriaBuilder,
|
||||||
Set<MappedSuperclass> mappedSuperclasses,
|
Set<MappedSuperclass> mappedSuperclasses,
|
||||||
TypeConfiguration typeConfiguration,
|
TypeConfiguration typeConfiguration,
|
||||||
|
@ -120,7 +117,7 @@ class MetadataContext {
|
||||||
return typeConfiguration.getJavaTypeDescriptorRegistry();
|
return typeConfiguration.getJavaTypeDescriptorRegistry();
|
||||||
}
|
}
|
||||||
|
|
||||||
DomainMetamodel getMetamodel() {
|
InflightRuntimeMetamodel getMetamodel() {
|
||||||
return metamodel;
|
return metamodel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,9 +138,9 @@ class MetadataContext {
|
||||||
return new HashSet<>( embeddables.values() );
|
return new HashSet<>( embeddables.values() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Class<?>, MappedSuperclassType<?>> getMappedSuperclassTypeMap() {
|
public Map<Class<?>, MappedSuperclassDomainType<?>> getMappedSuperclassTypeMap() {
|
||||||
// we need to actually build this map...
|
// we need to actually build this map...
|
||||||
final Map<Class<?>, MappedSuperclassType<?>> mappedSuperClassTypeMap = CollectionHelper.mapOfSize(
|
final Map<Class<?>, MappedSuperclassDomainType<?>> mappedSuperClassTypeMap = CollectionHelper.mapOfSize(
|
||||||
mappedSuperclassByMappedSuperclassMapping.size()
|
mappedSuperclassByMappedSuperclassMapping.size()
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,12 +6,28 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.internal;
|
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.BootstrapContext;
|
||||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
import org.hibernate.boot.spi.MetadataImplementor;
|
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.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.metamodel.spi.MetamodelImplementor;
|
||||||
|
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||||
|
import org.hibernate.persister.spi.PersisterFactory;
|
||||||
|
|
||||||
import static org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting.determineJpaMetaModelPopulationSetting;
|
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
|
* Responsible for interpreting the Hibernate boot metamodel into
|
||||||
* its runtime metamodel
|
* its runtime metamodel
|
||||||
*
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
* @see org.hibernate.boot.model
|
* @see org.hibernate.boot.model
|
||||||
* @see org.hibernate.metamodel
|
* @see org.hibernate.metamodel
|
||||||
*
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
*/
|
||||||
public class RuntimeModelCreationProcess {
|
public class RuntimeModelCreationProcess {
|
||||||
|
|
||||||
|
@ -76,31 +91,131 @@ public class RuntimeModelCreationProcess {
|
||||||
SessionFactoryImplementor sessionFactory,
|
SessionFactoryImplementor sessionFactory,
|
||||||
BootstrapContext bootstrapContext,
|
BootstrapContext bootstrapContext,
|
||||||
MetadataBuildingContext metadataBuildingContext,
|
MetadataBuildingContext metadataBuildingContext,
|
||||||
MetadataImplementor bootMetamodel) {
|
MetadataImplementor bootMetamodel,
|
||||||
return new RuntimeModelCreationProcess( sessionFactory, bootstrapContext, metadataBuildingContext ).execute();
|
JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting) {
|
||||||
|
return new RuntimeModelCreationProcess(
|
||||||
|
sessionFactory,
|
||||||
|
bootstrapContext,
|
||||||
|
metadataBuildingContext,
|
||||||
|
bootMetamodel,
|
||||||
|
jpaMetaModelPopulationSetting
|
||||||
|
).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final SessionFactoryImplementor sessionFactory;
|
private final SessionFactoryImplementor sessionFactory;
|
||||||
private final BootstrapContext bootstrapContext;
|
private final BootstrapContext bootstrapContext;
|
||||||
private final MetadataBuildingContext metadataBuildingContext;
|
private final MetadataBuildingContext metadataBuildingContext;
|
||||||
|
private final MetadataImplementor bootMetamodel;
|
||||||
|
private final JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting;
|
||||||
|
|
||||||
|
private JpaMetamodel jpaMetamodel;
|
||||||
|
private MetamodelImplementor domainMetamodel;
|
||||||
|
|
||||||
public RuntimeModelCreationProcess(
|
public RuntimeModelCreationProcess(
|
||||||
SessionFactoryImplementor sessionFactory,
|
SessionFactoryImplementor sessionFactory,
|
||||||
BootstrapContext bootstrapContext,
|
BootstrapContext bootstrapContext,
|
||||||
MetadataBuildingContext metadataBuildingContext) {
|
MetadataBuildingContext metadataBuildingContext,
|
||||||
|
MetadataImplementor bootMetamodel,
|
||||||
|
JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting) {
|
||||||
this.sessionFactory = sessionFactory;
|
this.sessionFactory = sessionFactory;
|
||||||
this.bootstrapContext = bootstrapContext;
|
this.bootstrapContext = bootstrapContext;
|
||||||
this.metadataBuildingContext = metadataBuildingContext;
|
this.metadataBuildingContext = metadataBuildingContext;
|
||||||
|
this.bootMetamodel = bootMetamodel;
|
||||||
|
this.jpaMetaModelPopulationSetting = jpaMetaModelPopulationSetting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public MetamodelImplementor execute() {
|
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 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<String, DomainDataRegionConfigImpl.Builder> 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<DomainDataRegionConfig> 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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,22 +12,23 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractDomainType<J> implements SimpleDomainType<J> {
|
public abstract class AbstractDomainType<J> implements SimpleDomainType<J> {
|
||||||
private final JpaMetamodel jpaMetamodel;
|
private JpaMetamodel jpaMetamodel;
|
||||||
|
|
||||||
private final JavaTypeDescriptor<J> javaTypeDescriptor;
|
private final JavaTypeDescriptor<J> javaTypeDescriptor;
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
public AbstractDomainType(
|
public AbstractDomainType(JavaTypeDescriptor<J> javaTypeDescriptor) {
|
||||||
JavaTypeDescriptor<J> javaTypeDescriptor,
|
|
||||||
JpaMetamodel jpaMetamodel) {
|
|
||||||
this.javaTypeDescriptor = javaTypeDescriptor;
|
this.javaTypeDescriptor = javaTypeDescriptor;
|
||||||
this.jpaMetamodel = jpaMetamodel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected JpaMetamodel jpaMetamodel() {
|
protected JpaMetamodel jpaMetamodel() {
|
||||||
return jpaMetamodel;
|
return jpaMetamodel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void injectJpaMetamodel(JpaMetamodel jpaMetamodel){
|
||||||
|
this.jpaMetamodel = jpaMetamodel;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JavaTypeDescriptor<J> getExpressableJavaTypeDescriptor() {
|
public JavaTypeDescriptor<J> getExpressableJavaTypeDescriptor() {
|
||||||
return javaTypeDescriptor;
|
return javaTypeDescriptor;
|
||||||
|
|
|
@ -45,9 +45,8 @@ public abstract class AbstractIdentifiableType<J>
|
||||||
IdentifiableDomainType<? super J> superType,
|
IdentifiableDomainType<? super J> superType,
|
||||||
boolean hasIdClass,
|
boolean hasIdClass,
|
||||||
boolean hasIdentifierProperty,
|
boolean hasIdentifierProperty,
|
||||||
boolean versioned,
|
boolean versioned) {
|
||||||
JpaMetamodel jpaMetamodel) {
|
super( typeName, javaTypeDescriptor, superType );
|
||||||
super( typeName, javaTypeDescriptor, superType, jpaMetamodel );
|
|
||||||
this.hasIdClass = hasIdClass;
|
this.hasIdClass = hasIdClass;
|
||||||
this.hasIdentifierProperty = hasIdentifierProperty;
|
this.hasIdentifierProperty = hasIdentifierProperty;
|
||||||
this.isVersioned = versioned;
|
this.isVersioned = versioned;
|
||||||
|
|
|
@ -48,9 +48,8 @@ public abstract class AbstractManagedType<J>
|
||||||
protected AbstractManagedType(
|
protected AbstractManagedType(
|
||||||
String hibernateTypeName,
|
String hibernateTypeName,
|
||||||
JavaTypeDescriptor<J> javaTypeDescriptor,
|
JavaTypeDescriptor<J> javaTypeDescriptor,
|
||||||
ManagedDomainType<? super J> superType,
|
ManagedDomainType<? super J> superType) {
|
||||||
JpaMetamodel jpaMetamodel) {
|
super( javaTypeDescriptor );
|
||||||
super( javaTypeDescriptor, jpaMetamodel );
|
|
||||||
this.hibernateTypeName = hibernateTypeName;
|
this.hibernateTypeName = hibernateTypeName;
|
||||||
this.superType = superType;
|
this.superType = superType;
|
||||||
|
|
||||||
|
|
|
@ -9,14 +9,10 @@ package org.hibernate.metamodel.model.domain.internal;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import javax.persistence.EntityGraph;
|
import javax.persistence.EntityGraph;
|
||||||
import javax.persistence.metamodel.EmbeddableType;
|
import javax.persistence.metamodel.EmbeddableType;
|
||||||
|
@ -24,44 +20,26 @@ import javax.persistence.metamodel.EntityType;
|
||||||
import javax.persistence.metamodel.ManagedType;
|
import javax.persistence.metamodel.ManagedType;
|
||||||
|
|
||||||
import org.hibernate.EntityNameResolver;
|
import org.hibernate.EntityNameResolver;
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.UnknownEntityTypeException;
|
import org.hibernate.UnknownEntityTypeException;
|
||||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
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.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.graph.RootGraph;
|
import org.hibernate.graph.RootGraph;
|
||||||
import org.hibernate.graph.spi.RootGraphImplementor;
|
import org.hibernate.graph.spi.RootGraphImplementor;
|
||||||
import org.hibernate.internal.EntityManagerMessageLogger;
|
import org.hibernate.internal.EntityManagerMessageLogger;
|
||||||
import org.hibernate.internal.HEMLogging;
|
import org.hibernate.internal.HEMLogging;
|
||||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
import org.hibernate.mapping.Collection;
|
import org.hibernate.metamodel.internal.InflightRuntimeMetamodel;
|
||||||
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.model.domain.EmbeddableDomainType;
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
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.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.spi.DomainMetamodel;
|
import org.hibernate.metamodel.spi.DomainMetamodel;
|
||||||
import org.hibernate.metamodel.spi.MetamodelImplementor;
|
import org.hibernate.metamodel.spi.MetamodelImplementor;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.Queryable;
|
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;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,7 +62,7 @@ public class DomainMetamodelImpl implements DomainMetamodel, MetamodelImplemento
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// JpaMetamodel
|
// JpaMetamodel
|
||||||
|
|
||||||
private final JpaMetamodelImpl jpaMetamodel;
|
private final JpaMetamodel jpaMetamodel;
|
||||||
|
|
||||||
// private final Map<Class<?>, EntityDomainType<?>> jpaEntityTypeMap = new ConcurrentHashMap<>();
|
// private final Map<Class<?>, EntityDomainType<?>> jpaEntityTypeMap = new ConcurrentHashMap<>();
|
||||||
// private final Map<String, EntityDomainType<?>> jpaEntityTypesByEntityName = new ConcurrentHashMap<>();
|
// private final Map<String, EntityDomainType<?>> jpaEntityTypesByEntityName = new ConcurrentHashMap<>();
|
||||||
|
@ -96,15 +74,15 @@ public class DomainMetamodelImpl implements DomainMetamodel, MetamodelImplemento
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// RuntimeModel
|
// RuntimeModel
|
||||||
|
|
||||||
private final Map<String, EntityPersister> entityPersisterMap = new ConcurrentHashMap<>();
|
private final Map<String, EntityPersister> entityPersisterMap;
|
||||||
private final Map<String, CollectionPersister> collectionPersisterMap = new ConcurrentHashMap<>();
|
private final Map<String, CollectionPersister> collectionPersisterMap;
|
||||||
private final Map<String, Set<String>> collectionRolesByEntityParticipant = new ConcurrentHashMap<>();
|
private final Map<String, Set<String>> collectionRolesByEntityParticipant;
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// DomainMetamodel
|
// DomainMetamodel
|
||||||
|
|
||||||
private final ConcurrentMap<EntityNameResolver, Object> entityNameResolvers = new ConcurrentHashMap<>();
|
private final Set<EntityNameResolver> entityNameResolvers;
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -143,254 +121,25 @@ public class DomainMetamodelImpl implements DomainMetamodel, MetamodelImplemento
|
||||||
|
|
||||||
private final Map<String, String[]> implementorsCache = new ConcurrentHashMap<>();
|
private final Map<String, String[]> implementorsCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public DomainMetamodelImpl(SessionFactoryImplementor sessionFactory, TypeConfiguration typeConfiguration) {
|
public DomainMetamodelImpl(
|
||||||
|
SessionFactoryImplementor sessionFactory,
|
||||||
|
InflightRuntimeMetamodel runtimeMetamodel,
|
||||||
|
JpaMetamodel jpaMetamodel) {
|
||||||
this.sessionFactory = sessionFactory;
|
this.sessionFactory = sessionFactory;
|
||||||
this.typeConfiguration = typeConfiguration;
|
this.jpaMetamodel = jpaMetamodel;
|
||||||
this.jpaMetamodel = new JpaMetamodelImpl( typeConfiguration );
|
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<String> 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<String> 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<String, DomainDataRegionConfigImpl.Builder> 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<DomainDataRegionConfig> 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
|
@Override
|
||||||
public java.util.Collection<EntityNameResolver> getEntityNameResolvers() {
|
public java.util.Collection<EntityNameResolver> getEntityNameResolvers() {
|
||||||
return entityNameResolvers.keySet();
|
return entityNameResolvers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerEntityNameResolvers(
|
|
||||||
EntityPersister persister,
|
|
||||||
Map<EntityNameResolver, Object> entityNameResolvers) {
|
|
||||||
if ( persister.getEntityMetamodel() == null || persister.getEntityMetamodel().getTuplizer() == null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
registerEntityNameResolvers( persister.getEntityMetamodel().getTuplizer(), entityNameResolvers );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void registerEntityNameResolvers(
|
|
||||||
EntityTuplizer tuplizer,
|
|
||||||
Map<EntityNameResolver, Object> 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<String, String> imports,
|
|
||||||
// Map<String, EntityPersister> entityPersisterMap,
|
|
||||||
// Map<Class, String> entityProxyInterfaceMap,
|
|
||||||
// ConcurrentHashMap<EntityNameResolver, Object> entityNameResolvers,
|
|
||||||
// Map<String, CollectionPersister> collectionPersisterMap,
|
|
||||||
// Map<String, Set<String>> collectionRolesByEntityParticipant,
|
|
||||||
// Map<Class<?>, EntityTypeImpl<?>> entities,
|
|
||||||
// Map<Class<?>, EmbeddableTypeImpl<?>> embeddables,
|
|
||||||
// Map<Class<?>, MappedSuperclassType<?>> mappedSuperclassTypeMap,
|
|
||||||
// Map<String, EntityTypeImpl<?>> 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
|
@Override
|
||||||
public TypeConfiguration getTypeConfiguration() {
|
public TypeConfiguration getTypeConfiguration() {
|
||||||
|
|
|
@ -28,7 +28,7 @@ public class EmbeddableTypeImpl<J>
|
||||||
implements EmbeddableDomainType<J>, Serializable {
|
implements EmbeddableDomainType<J>, Serializable {
|
||||||
|
|
||||||
public EmbeddableTypeImpl(JavaTypeDescriptor<J> javaTypeDescriptor, NodeBuilder nodeBuilder) {
|
public EmbeddableTypeImpl(JavaTypeDescriptor<J> javaTypeDescriptor, NodeBuilder nodeBuilder) {
|
||||||
super( javaTypeDescriptor.getJavaType().getName(), javaTypeDescriptor, null, nodeBuilder.getDomainModel() );
|
super( javaTypeDescriptor.getJavaType().getName(), javaTypeDescriptor, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmbeddableTypeImpl(
|
public EmbeddableTypeImpl(
|
||||||
|
@ -37,9 +37,11 @@ public class EmbeddableTypeImpl<J>
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
super(
|
super(
|
||||||
name,
|
name,
|
||||||
(JavaTypeDescriptor) nodeBuilder.getDomainModel().getTypeConfiguration().getJavaTypeDescriptorRegistry().getDescriptor( Map.class ),
|
(JavaTypeDescriptor) nodeBuilder.getDomainModel()
|
||||||
null,
|
.getTypeConfiguration()
|
||||||
nodeBuilder.getDomainModel()
|
.getJavaTypeDescriptorRegistry()
|
||||||
|
.getDescriptor( Map.class ),
|
||||||
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,16 +36,14 @@ public class EntityTypeImpl<J>
|
||||||
public EntityTypeImpl(
|
public EntityTypeImpl(
|
||||||
JavaTypeDescriptor<J> javaTypeDescriptor,
|
JavaTypeDescriptor<J> javaTypeDescriptor,
|
||||||
IdentifiableDomainType<? super J> superType,
|
IdentifiableDomainType<? super J> superType,
|
||||||
PersistentClass persistentClass,
|
PersistentClass persistentClass) {
|
||||||
JpaMetamodel jpaMetamodel) {
|
|
||||||
super(
|
super(
|
||||||
persistentClass.getEntityName(),
|
persistentClass.getEntityName(),
|
||||||
javaTypeDescriptor,
|
javaTypeDescriptor,
|
||||||
superType,
|
superType,
|
||||||
persistentClass.getDeclaredIdentifierMapper() != null || ( superType != null && superType.hasIdClass() ),
|
persistentClass.getDeclaredIdentifierMapper() != null || ( superType != null && superType.hasIdClass() ),
|
||||||
persistentClass.hasIdentifierProperty(),
|
persistentClass.hasIdentifierProperty(),
|
||||||
persistentClass.isVersioned(),
|
persistentClass.isVersioned()
|
||||||
jpaMetamodel
|
|
||||||
);
|
);
|
||||||
this.jpaEntityName = persistentClass.getJpaEntityName();
|
this.jpaEntityName = persistentClass.getJpaEntityName();
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import javax.persistence.EntityGraph;
|
import javax.persistence.EntityGraph;
|
||||||
import javax.persistence.NamedAttributeNode;
|
import javax.persistence.NamedAttributeNode;
|
||||||
import javax.persistence.NamedEntityGraph;
|
import javax.persistence.NamedEntityGraph;
|
||||||
|
@ -23,11 +21,9 @@ import javax.persistence.metamodel.Attribute;
|
||||||
import javax.persistence.metamodel.EmbeddableType;
|
import javax.persistence.metamodel.EmbeddableType;
|
||||||
import javax.persistence.metamodel.EntityType;
|
import javax.persistence.metamodel.EntityType;
|
||||||
import javax.persistence.metamodel.ManagedType;
|
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.ClassLoaderService;
|
||||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||||
import org.hibernate.boot.spi.MetadataImplementor;
|
|
||||||
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||||
import org.hibernate.graph.internal.RootGraphImpl;
|
import org.hibernate.graph.internal.RootGraphImpl;
|
||||||
import org.hibernate.graph.spi.AttributeNodeImplementor;
|
import org.hibernate.graph.spi.AttributeNodeImplementor;
|
||||||
|
@ -38,20 +34,14 @@ import org.hibernate.internal.EntityManagerMessageLogger;
|
||||||
import org.hibernate.internal.HEMLogging;
|
import org.hibernate.internal.HEMLogging;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.mapping.MappedSuperclass;
|
import org.hibernate.metamodel.internal.InflightRuntimeMetamodel;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.metamodel.model.domain.AbstractDomainType;
|
||||||
import org.hibernate.metamodel.internal.JpaMetaModelPopulationSetting;
|
|
||||||
import org.hibernate.metamodel.internal.JpaStaticMetaModelPopulationSetting;
|
|
||||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
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.JpaMetamodel;
|
||||||
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType;
|
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.query.sqm.tree.domain.SqmPolymorphicRootDescriptor;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,234 +53,42 @@ public class JpaMetamodelImpl implements JpaMetamodel {
|
||||||
|
|
||||||
private final TypeConfiguration typeConfiguration;
|
private final TypeConfiguration typeConfiguration;
|
||||||
|
|
||||||
private final Map<String, EntityDomainType<?>> entityDescriptorMap = new ConcurrentHashMap<>();
|
private final Map<String, EntityDomainType<?>> entityDescriptorMap;
|
||||||
private final Map<Class, EntityDomainType<?>> strictEntityDescriptorMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
private final Map<Class<?>, MappedSuperclassType<?>> mappedSuperclassTypeMap = new ConcurrentHashMap<>();
|
private final Map<Class<?>, MappedSuperclassDomainType<?>> mappedSuperclassTypeMap;
|
||||||
|
|
||||||
private final Map<Class, EmbeddableDomainType<?>> embeddableDescriptorMap = new ConcurrentHashMap<>();
|
private final Map<Class, EmbeddableDomainType<?>> embeddableDescriptorMap;
|
||||||
|
|
||||||
private final Map<String, String> nameToImportNameMap = new ConcurrentHashMap<>();
|
private final Map<String, String> nameToImportNameMap;
|
||||||
|
|
||||||
private final transient Map<String, RootGraphImplementor> entityGraphMap = new ConcurrentHashMap<>();
|
private final transient Map<String, RootGraphImplementor> entityGraphMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final Map<Class, SqmPolymorphicRootDescriptor<?>> polymorphicEntityReferenceMap = new ConcurrentHashMap<>();
|
private final Map<Class, SqmPolymorphicRootDescriptor<?>> polymorphicEntityReferenceMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public JpaMetamodelImpl(TypeConfiguration typeConfiguration) {
|
private final Map<Class, String> entityProxyInterfaceMap;
|
||||||
this.typeConfiguration = typeConfiguration;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
for ( PersistentClass entityBinding : mappingMetadata.getEntityBindings() ) {
|
|
||||||
locateOrBuildEntityType( entityBinding, context );
|
|
||||||
}
|
|
||||||
handleUnusedMappedSuperclasses( context );
|
|
||||||
|
|
||||||
context.wrapUp();
|
|
||||||
|
|
||||||
this.nameToImportNameMap.putAll( mappingMetadata.getImports() );
|
|
||||||
|
|
||||||
this.strictEntityDescriptorMap.putAll( context.getEntityTypeMap() );
|
|
||||||
this.entityDescriptorMap.putAll( context.getEntityTypesByEntityName() );
|
|
||||||
this.mappedSuperclassTypeMap.putAll( context.getMappedSuperclassTypeMap() );
|
|
||||||
|
|
||||||
for ( EmbeddableDomainType<?> embeddable : context.getEmbeddableTypeSet() ) {
|
|
||||||
this.embeddableDescriptorMap.put( embeddable.getJavaType(), embeddable );
|
|
||||||
}
|
|
||||||
|
|
||||||
applyNamedEntityGraphs( mappingMetadata.getNamedEntityGraphs().values() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private void applyNamedEntityGraphs(java.util.Collection<NamedEntityGraphDefinition> namedEntityGraphs) {
|
|
||||||
for ( NamedEntityGraphDefinition definition : namedEntityGraphs ) {
|
|
||||||
log.debugf(
|
|
||||||
"Applying named entity graph [name=%s, entity-name=%s, jpa-entity-name=%s",
|
|
||||||
definition.getRegisteredName(),
|
|
||||||
definition.getEntityName(),
|
|
||||||
definition.getJpaEntityName()
|
|
||||||
);
|
|
||||||
final EntityDomainType entityType = entity( definition.getEntityName() );
|
|
||||||
if ( entityType == null ) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Attempted to register named entity graph [" + definition.getRegisteredName()
|
|
||||||
+ "] for unknown entity [" + definition.getEntityName() + "]"
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final RootGraphImpl entityGraph = new RootGraphImpl(
|
|
||||||
definition.getRegisteredName(),
|
|
||||||
entityType,
|
|
||||||
this
|
|
||||||
);
|
|
||||||
|
|
||||||
final NamedEntityGraph namedEntityGraph = definition.getAnnotation();
|
|
||||||
|
|
||||||
if ( namedEntityGraph.includeAllAttributes() ) {
|
|
||||||
for ( Object attributeObject : entityType.getAttributes() ) {
|
|
||||||
entityGraph.addAttributeNodes( (Attribute) attributeObject );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( namedEntityGraph.attributeNodes() != null ) {
|
|
||||||
applyNamedAttributeNodes( namedEntityGraph.attributeNodes(), namedEntityGraph, entityGraph );
|
|
||||||
}
|
|
||||||
|
|
||||||
entityGraphMap.put( definition.getRegisteredName(), entityGraph );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyNamedAttributeNodes(
|
|
||||||
NamedAttributeNode[] namedAttributeNodes,
|
|
||||||
NamedEntityGraph namedEntityGraph,
|
|
||||||
GraphImplementor graphNode) {
|
|
||||||
for ( NamedAttributeNode namedAttributeNode : namedAttributeNodes ) {
|
|
||||||
final String value = namedAttributeNode.value();
|
|
||||||
AttributeNodeImplementor attributeNode = graphNode.addAttributeNode( value );
|
|
||||||
if ( StringHelper.isNotEmpty( namedAttributeNode.subgraph() ) ) {
|
|
||||||
final SubGraphImplementor subgraph = attributeNode.makeSubGraph();
|
|
||||||
applyNamedSubgraphs(
|
|
||||||
namedEntityGraph,
|
|
||||||
namedAttributeNode.subgraph(),
|
|
||||||
subgraph
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ( StringHelper.isNotEmpty( namedAttributeNode.keySubgraph() ) ) {
|
|
||||||
final SubGraphImplementor subgraph = attributeNode.makeKeySubGraph();
|
|
||||||
|
|
||||||
applyNamedSubgraphs(
|
|
||||||
namedEntityGraph,
|
|
||||||
namedAttributeNode.keySubgraph(),
|
|
||||||
subgraph
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyNamedSubgraphs(
|
|
||||||
NamedEntityGraph namedEntityGraph,
|
|
||||||
String subgraphName,
|
|
||||||
SubGraphImplementor subgraph) {
|
|
||||||
for ( NamedSubgraph namedSubgraph : namedEntityGraph.subgraphs() ) {
|
|
||||||
if ( subgraphName.equals( namedSubgraph.name() ) ) {
|
|
||||||
applyNamedAttributeNodes(
|
|
||||||
namedSubgraph.attributeNodes(),
|
|
||||||
namedEntityGraph,
|
|
||||||
subgraph
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void handleUnusedMappedSuperclasses(MetadataContext context) {
|
|
||||||
final Set<MappedSuperclass> 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(
|
public JpaMetamodelImpl(
|
||||||
PersistentClass persistentClass,
|
InflightRuntimeMetamodel runtimeMetamodel,
|
||||||
MetadataContext context) {
|
java.util.Collection<NamedEntityGraphDefinition> namedEntityGraphDefinitions) {
|
||||||
EntityDomainType<?> entityType = context.locateEntityType( persistentClass );
|
this.typeConfiguration = runtimeMetamodel.getTypeConfiguration();
|
||||||
if ( entityType == null ) {
|
|
||||||
entityType = buildEntityType( persistentClass, context );
|
|
||||||
}
|
|
||||||
return entityType;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO remove / reduce @SW scope
|
entityDescriptorMap = runtimeMetamodel.getJpaEntityTypeMap();
|
||||||
@SuppressWarnings("unchecked")
|
mappedSuperclassTypeMap = runtimeMetamodel.getJpaMappedSuperclassTypeMap();
|
||||||
private static EntityTypeImpl<?> buildEntityType(PersistentClass persistentClass, MetadataContext context) {
|
embeddableDescriptorMap = runtimeMetamodel.getJpaEmbeddableDescriptorMap();
|
||||||
final Class javaType = persistentClass.getMappedClass();
|
|
||||||
context.pushEntityWorkedOn( persistentClass );
|
entityDescriptorMap.values()
|
||||||
final MappedSuperclass superMappedSuperclass = persistentClass.getSuperMappedSuperclass();
|
.forEach( domainType -> ( (AbstractDomainType) domainType ).injectJpaMetamodel( this ) );
|
||||||
IdentifiableDomainType<?> superType = superMappedSuperclass == null
|
mappedSuperclassTypeMap.values().forEach( domainType -> ( (AbstractDomainType) domainType ).injectJpaMetamodel(
|
||||||
? null
|
this ) );
|
||||||
: locateOrBuildMappedSuperclassType( superMappedSuperclass, context );
|
entityDescriptorMap.values()
|
||||||
//no mappedSuperclass, check for a super entity
|
.forEach( domainType -> ( (AbstractDomainType) domainType ).injectJpaMetamodel( this ) );
|
||||||
if ( superType == null ) {
|
|
||||||
final PersistentClass superPersistentClass = persistentClass.getSuperclass();
|
nameToImportNameMap = runtimeMetamodel.getNameToImportNameMap();
|
||||||
superType = superPersistentClass == null
|
entityProxyInterfaceMap = runtimeMetamodel.getEntityProxyInterfaceMap();
|
||||||
? null
|
applyNamedEntityGraphs( namedEntityGraphDefinitions );
|
||||||
: 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
|
@Override
|
||||||
public TypeConfiguration getTypeConfiguration() {
|
public TypeConfiguration getTypeConfiguration() {
|
||||||
return typeConfiguration;
|
return typeConfiguration;
|
||||||
|
@ -353,7 +151,7 @@ public class JpaMetamodelImpl implements JpaMetamodel {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> ManagedDomainType<X> managedType(Class<X> cls) {
|
public <X> ManagedDomainType<X> managedType(Class<X> cls) {
|
||||||
ManagedType<?> type = strictEntityDescriptorMap.get( cls );
|
ManagedType<?> type = entityDescriptorMap.get( cls );
|
||||||
if ( type == null ) {
|
if ( type == null ) {
|
||||||
type = mappedSuperclassTypeMap.get( cls );
|
type = mappedSuperclassTypeMap.get( cls );
|
||||||
}
|
}
|
||||||
|
@ -371,7 +169,7 @@ public class JpaMetamodelImpl implements JpaMetamodel {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> EntityDomainType<X> entity(Class<X> cls) {
|
public <X> EntityDomainType<X> entity(Class<X> cls) {
|
||||||
final EntityType<?> entityType = strictEntityDescriptorMap.get( cls );
|
final EntityType<?> entityType = entityDescriptorMap.get( cls );
|
||||||
if ( entityType == null ) {
|
if ( entityType == null ) {
|
||||||
throw new IllegalArgumentException( "Not an entity: " + cls );
|
throw new IllegalArgumentException( "Not an entity: " + cls );
|
||||||
}
|
}
|
||||||
|
@ -485,6 +283,88 @@ public class JpaMetamodelImpl implements JpaMetamodel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private void applyNamedEntityGraphs(java.util.Collection<NamedEntityGraphDefinition> namedEntityGraphs) {
|
||||||
|
for ( NamedEntityGraphDefinition definition : namedEntityGraphs ) {
|
||||||
|
log.debugf(
|
||||||
|
"Applying named entity graph [name=%s, entity-name=%s, jpa-entity-name=%s",
|
||||||
|
definition.getRegisteredName(),
|
||||||
|
definition.getEntityName(),
|
||||||
|
definition.getJpaEntityName()
|
||||||
|
);
|
||||||
|
final EntityDomainType entityType = entity( definition.getEntityName() );
|
||||||
|
if ( entityType == null ) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Attempted to register named entity graph [" + definition.getRegisteredName()
|
||||||
|
+ "] for unknown entity [" + definition.getEntityName() + "]"
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final RootGraphImpl entityGraph = new RootGraphImpl(
|
||||||
|
definition.getRegisteredName(),
|
||||||
|
entityType,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
|
||||||
|
final NamedEntityGraph namedEntityGraph = definition.getAnnotation();
|
||||||
|
|
||||||
|
if ( namedEntityGraph.includeAllAttributes() ) {
|
||||||
|
for ( Object attributeObject : entityType.getAttributes() ) {
|
||||||
|
entityGraph.addAttributeNodes( (Attribute) attributeObject );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( namedEntityGraph.attributeNodes() != null ) {
|
||||||
|
applyNamedAttributeNodes( namedEntityGraph.attributeNodes(), namedEntityGraph, entityGraph );
|
||||||
|
}
|
||||||
|
|
||||||
|
entityGraphMap.put( definition.getRegisteredName(), entityGraph );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyNamedAttributeNodes(
|
||||||
|
NamedAttributeNode[] namedAttributeNodes,
|
||||||
|
NamedEntityGraph namedEntityGraph,
|
||||||
|
GraphImplementor graphNode) {
|
||||||
|
for ( NamedAttributeNode namedAttributeNode : namedAttributeNodes ) {
|
||||||
|
final String value = namedAttributeNode.value();
|
||||||
|
AttributeNodeImplementor attributeNode = graphNode.addAttributeNode( value );
|
||||||
|
if ( StringHelper.isNotEmpty( namedAttributeNode.subgraph() ) ) {
|
||||||
|
final SubGraphImplementor subgraph = attributeNode.makeSubGraph();
|
||||||
|
applyNamedSubgraphs(
|
||||||
|
namedEntityGraph,
|
||||||
|
namedAttributeNode.subgraph(),
|
||||||
|
subgraph
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ( StringHelper.isNotEmpty( namedAttributeNode.keySubgraph() ) ) {
|
||||||
|
final SubGraphImplementor subgraph = attributeNode.makeKeySubGraph();
|
||||||
|
|
||||||
|
applyNamedSubgraphs(
|
||||||
|
namedEntityGraph,
|
||||||
|
namedAttributeNode.keySubgraph(),
|
||||||
|
subgraph
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyNamedSubgraphs(
|
||||||
|
NamedEntityGraph namedEntityGraph,
|
||||||
|
String subgraphName,
|
||||||
|
SubGraphImplementor subgraph) {
|
||||||
|
for ( NamedSubgraph namedSubgraph : namedEntityGraph.subgraphs() ) {
|
||||||
|
if ( subgraphName.equals( namedSubgraph.name() ) ) {
|
||||||
|
applyNamedAttributeNodes(
|
||||||
|
namedSubgraph.attributeNodes(),
|
||||||
|
namedEntityGraph,
|
||||||
|
subgraph
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private <X> Class<X> resolveRequestedClass(String entityName) {
|
private <X> Class<X> resolveRequestedClass(String entityName) {
|
||||||
try {
|
try {
|
||||||
return getServiceRegistry().getService( ClassLoaderService.class ).classForName( entityName );
|
return getServiceRegistry().getService( ClassLoaderService.class ).classForName( entityName );
|
||||||
|
@ -498,7 +378,7 @@ public class JpaMetamodelImpl implements JpaMetamodel {
|
||||||
public <T> EntityDomainType<T> resolveEntityReference(Class<T> javaType) {
|
public <T> EntityDomainType<T> resolveEntityReference(Class<T> javaType) {
|
||||||
// try the incoming Java type as a "strict" entity reference
|
// 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 ) {
|
if ( descriptor != null ) {
|
||||||
return (EntityDomainType<T>) descriptor;
|
return (EntityDomainType<T>) descriptor;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ import org.hibernate.graph.spi.SubGraphImplementor;
|
||||||
import org.hibernate.mapping.MappedSuperclass;
|
import org.hibernate.mapping.MappedSuperclass;
|
||||||
import org.hibernate.metamodel.model.domain.AbstractIdentifiableType;
|
import org.hibernate.metamodel.model.domain.AbstractIdentifiableType;
|
||||||
import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
|
import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
|
||||||
import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType;
|
import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType;
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
|
||||||
|
@ -23,16 +22,14 @@ public class MappedSuperclassTypeImpl<X> extends AbstractIdentifiableType<X> imp
|
||||||
public MappedSuperclassTypeImpl(
|
public MappedSuperclassTypeImpl(
|
||||||
JavaTypeDescriptor<X> javaTypeDescriptor,
|
JavaTypeDescriptor<X> javaTypeDescriptor,
|
||||||
MappedSuperclass mappedSuperclass,
|
MappedSuperclass mappedSuperclass,
|
||||||
IdentifiableDomainType<? super X> superType,
|
IdentifiableDomainType<? super X> superType) {
|
||||||
JpaMetamodel jpaMetamodel) {
|
|
||||||
super(
|
super(
|
||||||
javaTypeDescriptor.getJavaType().getName(),
|
javaTypeDescriptor.getJavaType().getName(),
|
||||||
javaTypeDescriptor,
|
javaTypeDescriptor,
|
||||||
superType,
|
superType,
|
||||||
mappedSuperclass.getDeclaredIdentifierMapper() != null || ( superType != null && superType.hasIdClass() ),
|
mappedSuperclass.getDeclaredIdentifierMapper() != null || ( superType != null && superType.hasIdClass() ),
|
||||||
mappedSuperclass.hasIdentifierProperty(),
|
mappedSuperclass.hasIdentifierProperty(),
|
||||||
mappedSuperclass.isVersioned(),
|
mappedSuperclass.isVersioned()
|
||||||
jpaMetamodel
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ public interface AssociationType extends Type {
|
||||||
/**
|
/**
|
||||||
* Get the foreign key directionality of this association
|
* Get the foreign key directionality of this association
|
||||||
*/
|
*/
|
||||||
public ForeignKeyDirection getForeignKeyDirection();
|
ForeignKeyDirection getForeignKeyDirection();
|
||||||
|
|
||||||
//TODO: move these to a new JoinableType abstract class,
|
//TODO: move these to a new JoinableType abstract class,
|
||||||
//extended by EntityType and PersistentCollectionType:
|
//extended by EntityType and PersistentCollectionType:
|
||||||
|
@ -32,47 +32,47 @@ public interface AssociationType extends Type {
|
||||||
* Is the primary key of the owning entity table
|
* Is the primary key of the owning entity table
|
||||||
* to be used in the join?
|
* to be used in the join?
|
||||||
*/
|
*/
|
||||||
public boolean useLHSPrimaryKey();
|
boolean useLHSPrimaryKey();
|
||||||
/**
|
/**
|
||||||
* Get the name of a property in the owning entity
|
* Get the name of a property in the owning entity
|
||||||
* that provides the join key (null if the identifier)
|
* that provides the join key (null if the identifier)
|
||||||
*/
|
*/
|
||||||
public String getLHSPropertyName();
|
String getLHSPropertyName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of a unique property of the associated entity
|
* The name of a unique property of the associated entity
|
||||||
* that provides the join key (null if the identifier of
|
* that provides the join key (null if the identifier of
|
||||||
* an entity, or key of a collection)
|
* an entity, or key of a collection)
|
||||||
*/
|
*/
|
||||||
public String getRHSUniqueKeyPropertyName();
|
String getRHSUniqueKeyPropertyName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the "persister" for this association - a class or
|
* Get the "persister" for this association - a class or
|
||||||
* collection persister
|
* collection persister
|
||||||
*/
|
*/
|
||||||
public Joinable getAssociatedJoinable(SessionFactoryImplementor factory) throws MappingException;
|
Joinable getAssociatedJoinable(SessionFactoryImplementor factory) throws MappingException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the entity name of the associated entity
|
* 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
|
* Get the "filtering" SQL fragment that is applied in the
|
||||||
* SQL on clause, in addition to the usual join condition
|
* 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;
|
throws MappingException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the "filtering" SQL fragment that is applied in the
|
* Get the "filtering" SQL fragment that is applied in the
|
||||||
* SQL on clause, in addition to the usual join condition
|
* SQL on clause, in addition to the usual join condition
|
||||||
*/
|
*/
|
||||||
public String getOnCondition(String alias, SessionFactoryImplementor factory, Map enabledFilters, Set<String> treatAsDeclarations);
|
String getOnCondition(String alias, SessionFactoryImplementor factory, Map enabledFilters, Set<String> treatAsDeclarations);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do we dirty check this association, even when there are
|
* Do we dirty check this association, even when there are
|
||||||
* no columns to be updated?
|
* no columns to be updated?
|
||||||
*/
|
*/
|
||||||
public abstract boolean isAlwaysDirtyChecked();
|
boolean isAlwaysDirtyChecked();
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,7 +184,7 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
|
||||||
|
|
||||||
scope.setSessionFactory( sessionFactory );
|
scope.setSessionFactory( sessionFactory );
|
||||||
sessionFactory.addObserver( this );
|
sessionFactory.addObserver( this );
|
||||||
return new DomainMetamodelImpl( sessionFactory, this );
|
return new DomainMetamodelImpl( sessionFactory, this, this.jpaMetamodel );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -94,7 +94,9 @@ public class MetadataTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
.addAnnotatedClass( WithGenericCollection.class )
|
.addAnnotatedClass( WithGenericCollection.class )
|
||||||
.buildMetadata();
|
.buildMetadata();
|
||||||
SessionFactoryImplementor sfi = (SessionFactoryImplementor) metadata.buildSessionFactory();
|
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 );
|
metamodel.initialize( (MetadataImplementor) metadata, JpaMetaModelPopulationSetting.IGNORE_UNSUPPORTED );
|
||||||
sfi.close();
|
sfi.close();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue