HHH-16115 - Develop an intermediate metamodel binding model

HHH-16116 - Bind intermediate metamodel into PersistentClass, et al.
This commit is contained in:
Steve Ebersole 2023-03-05 12:54:45 -06:00
parent 8e8bc00434
commit ff6d79ca63
12 changed files with 212 additions and 23 deletions

View File

@ -23,6 +23,7 @@ import org.hibernate.Internal;
import org.hibernate.boot.archive.spi.InputStreamAccess; import org.hibernate.boot.archive.spi.InputStreamAccess;
import org.hibernate.boot.internal.MetadataBuilderImpl; import org.hibernate.boot.internal.MetadataBuilderImpl;
import org.hibernate.boot.jaxb.internal.XmlSources; import org.hibernate.boot.jaxb.internal.XmlSources;
import org.hibernate.boot.jaxb.spi.BindableMappingDescriptor;
import org.hibernate.boot.jaxb.spi.Binding; import org.hibernate.boot.jaxb.spi.Binding;
import org.hibernate.boot.jaxb.spi.XmlSource; import org.hibernate.boot.jaxb.spi.XmlSource;
import org.hibernate.boot.registry.BootstrapServiceRegistry; import org.hibernate.boot.registry.BootstrapServiceRegistry;
@ -64,7 +65,7 @@ public class MetadataSources implements Serializable {
private XmlMappingBinderAccess xmlMappingBinderAccess; private XmlMappingBinderAccess xmlMappingBinderAccess;
private List<Binding<?>> xmlBindings; private List<Binding<BindableMappingDescriptor>> xmlBindings;
private LinkedHashSet<Class<?>> annotatedClasses; private LinkedHashSet<Class<?>> annotatedClasses;
private LinkedHashSet<String> annotatedClassNames; private LinkedHashSet<String> annotatedClassNames;
private LinkedHashSet<String> annotatedPackages; private LinkedHashSet<String> annotatedPackages;
@ -120,7 +121,7 @@ public class MetadataSources implements Serializable {
return xmlMappingBinderAccess; return xmlMappingBinderAccess;
} }
public List<Binding<?>> getXmlBindings() { public List<Binding<BindableMappingDescriptor>> getXmlBindings() {
return xmlBindings == null ? Collections.emptyList() : xmlBindings; return xmlBindings == null ? Collections.emptyList() : xmlBindings;
} }
@ -371,7 +372,8 @@ public class MetadataSources implements Serializable {
* @return this (for method chaining purposes) * @return this (for method chaining purposes)
*/ */
public MetadataSources addXmlBinding(Binding<?> binding) { public MetadataSources addXmlBinding(Binding<?> binding) {
getXmlBindingsForWrite().add( binding ); //noinspection unchecked
getXmlBindingsForWrite().add( (Binding<BindableMappingDescriptor>) binding );
return this; return this;
} }
@ -547,7 +549,7 @@ public class MetadataSources implements Serializable {
return this; return this;
} }
private List<Binding<?>> getXmlBindingsForWrite() { private List<Binding<BindableMappingDescriptor>> getXmlBindingsForWrite() {
if ( xmlBindings == null ) { if ( xmlBindings == null ) {
xmlBindings = new ArrayList<>(); xmlBindings = new ArrayList<>();
} }

View File

@ -513,6 +513,10 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
return this; return this;
} }
public AttributeConverterManager getAttributeConverterManager() {
return attributeConverterManager;
}
@Override @Override
public void addAttributeConverter(Class<? extends AttributeConverter<?,?>> converterClass) { public void addAttributeConverter(Class<? extends AttributeConverter<?,?>> converterClass) {
attributeConverterManager.addConverter( attributeConverterManager.addConverter(

View File

@ -46,6 +46,13 @@ public class AttributeConverterManager implements ConverterAutoApplyHandler {
private Map<Class<?>, ConverterDescriptor> attributeConverterDescriptorsByClass; private Map<Class<?>, ConverterDescriptor> attributeConverterDescriptorsByClass;
private Map<Class<?>, RegisteredConversion> registeredConversionsByDomainType; private Map<Class<?>, RegisteredConversion> registeredConversionsByDomainType;
public RegisteredConversion findRegisteredConversion(Class<?> domainType) {
if ( registeredConversionsByDomainType == null ) {
return null;
}
return registeredConversionsByDomainType.get( domainType );
}
public void addConverter(ConverterDescriptor descriptor) { public void addConverter(ConverterDescriptor descriptor) {
if ( log.isTraceEnabled() ) { if ( log.isTraceEnabled() ) {
log.tracef( "Starting AttributeConverterManager#addConverter : `%s`", log.tracef( "Starting AttributeConverterManager#addConverter : `%s`",

View File

@ -317,7 +317,7 @@ public class InheritanceState {
//add MappedSuperclass if not already there //add MappedSuperclass if not already there
mappedSuperclass = buildingContext.getMetadataCollector().getMappedSuperclass( type ); mappedSuperclass = buildingContext.getMetadataCollector().getMappedSuperclass( type );
if ( mappedSuperclass == null ) { if ( mappedSuperclass == null ) {
mappedSuperclass = new org.hibernate.mapping.MappedSuperclass( parentSuperclass, superEntity ); mappedSuperclass = new org.hibernate.mapping.MappedSuperclass( parentSuperclass, superEntity, persistentClass.getImplicitTable() );
mappedSuperclass.setMappedClass( type ); mappedSuperclass.setMappedClass( type );
buildingContext.getMetadataCollector().addMappedSuperclass( type, mappedSuperclass ); buildingContext.getMetadataCollector().addMappedSuperclass( type, mappedSuperclass );
} }

View File

@ -242,6 +242,12 @@ public class Identifier implements Comparable<Identifier> {
return getCanonicalName().equals( that.getCanonicalName() ); return getCanonicalName().equals( that.getCanonicalName() );
} }
public boolean matches(String name) {
return isQuoted()
? text.equals( name )
: text.equalsIgnoreCase( name );
}
@Override @Override
public int hashCode() { public int hashCode() {
return isQuoted ? text.hashCode() : text.toLowerCase( Locale.ENGLISH ).hashCode(); return isQuoted ? text.hashCode() : text.toLowerCase( Locale.ENGLISH ).hashCode();

View File

@ -17,20 +17,23 @@ import java.util.Set;
import org.hibernate.Internal; import org.hibernate.Internal;
import org.hibernate.boot.MetadataSources; import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.jaxb.spi.BindableMappingDescriptor;
import org.hibernate.boot.jaxb.spi.Binding; import org.hibernate.boot.jaxb.spi.Binding;
import org.hibernate.boot.model.convert.spi.ConverterDescriptor; import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
import org.hibernate.boot.model.process.spi.ManagedResources; import org.hibernate.boot.model.process.spi.ManagedResources;
import org.hibernate.boot.spi.BootstrapContext; import org.hibernate.boot.spi.BootstrapContext;
import jakarta.persistence.AttributeConverter;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class ManagedResourcesImpl implements ManagedResources { public class ManagedResourcesImpl implements ManagedResources {
private Map<Class, ConverterDescriptor> attributeConverterDescriptorMap = new HashMap<>(); private final Map<Class<? extends AttributeConverter>, ConverterDescriptor> attributeConverterDescriptorMap = new HashMap<>();
private Set<Class> annotatedClassReferences = new LinkedHashSet<>(); private final Set<Class<?>> annotatedClassReferences = new LinkedHashSet<>();
private Set<String> annotatedClassNames = new LinkedHashSet<>(); private final Set<String> annotatedClassNames = new LinkedHashSet<>();
private Set<String> annotatedPackageNames = new LinkedHashSet<>(); private final Set<String> annotatedPackageNames = new LinkedHashSet<>();
private List<Binding> mappingFileBindings = new ArrayList<>(); private final List<Binding<BindableMappingDescriptor>> mappingFileBindings = new ArrayList<>();
private Map<String, Class<?>> extraQueryImports; private Map<String, Class<?>> extraQueryImports;
public static ManagedResourcesImpl baseline(MetadataSources sources, BootstrapContext bootstrapContext) { public static ManagedResourcesImpl baseline(MetadataSources sources, BootstrapContext bootstrapContext) {
@ -44,7 +47,7 @@ public class ManagedResourcesImpl implements ManagedResources {
return impl; return impl;
} }
private ManagedResourcesImpl() { public ManagedResourcesImpl() {
} }
@Override @Override
@ -53,7 +56,7 @@ public class ManagedResourcesImpl implements ManagedResources {
} }
@Override @Override
public Collection<Class> getAnnotatedClassReferences() { public Collection<Class<?>> getAnnotatedClassReferences() {
return Collections.unmodifiableSet( annotatedClassReferences ); return Collections.unmodifiableSet( annotatedClassReferences );
} }
@ -68,7 +71,7 @@ public class ManagedResourcesImpl implements ManagedResources {
} }
@Override @Override
public Collection<Binding> getXmlMappingBindings() { public Collection<Binding<BindableMappingDescriptor>> getXmlMappingBindings() {
return Collections.unmodifiableList( mappingFileBindings ); return Collections.unmodifiableList( mappingFileBindings );
} }
@ -87,7 +90,7 @@ public class ManagedResourcesImpl implements ManagedResources {
} }
@Internal @Internal
public void addAnnotatedClassReference(Class annotatedClassReference) { public void addAnnotatedClassReference(Class<?> annotatedClassReference) {
annotatedClassReferences.add( annotatedClassReference ); annotatedClassReferences.add( annotatedClassReference );
} }
@ -102,7 +105,7 @@ public class ManagedResourcesImpl implements ManagedResources {
} }
@Internal @Internal
public void addXmlBinding(Binding binding) { public void addXmlBinding(Binding<BindableMappingDescriptor> binding) {
mappingFileBindings.add( binding ); mappingFileBindings.add( binding );
} }
} }

View File

@ -9,6 +9,7 @@ package org.hibernate.boot.model.process.spi;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import org.hibernate.boot.jaxb.spi.BindableMappingDescriptor;
import org.hibernate.boot.jaxb.spi.Binding; import org.hibernate.boot.jaxb.spi.Binding;
import org.hibernate.boot.model.convert.spi.ConverterDescriptor; import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
@ -40,7 +41,7 @@ public interface ManagedResources {
* *
* @return The list of entity/component classes known by Class reference. * @return The list of entity/component classes known by Class reference.
*/ */
Collection<Class> getAnnotatedClassReferences(); Collection<Class<?>> getAnnotatedClassReferences();
/** /**
* Informational access to any entity and component classes in the user domain model known by name. * Informational access to any entity and component classes in the user domain model known by name.
@ -64,7 +65,7 @@ public interface ManagedResources {
* *
* @return The list of bindings for all known XML mapping files. * @return The list of bindings for all known XML mapping files.
*/ */
Collection<Binding> getXmlMappingBindings(); Collection<Binding<BindableMappingDescriptor>> getXmlMappingBindings();
Map<String,Class<?>> getExtraQueryImports(); Map<String,Class<?>> getExtraQueryImports();
} }

View File

@ -12,6 +12,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmHibernateMapping; import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmHibernateMapping;
import org.hibernate.boot.jaxb.spi.BindableMappingDescriptor;
import org.hibernate.boot.jaxb.spi.Binding; import org.hibernate.boot.jaxb.spi.Binding;
import org.hibernate.boot.model.process.spi.ManagedResources; import org.hibernate.boot.model.process.spi.ManagedResources;
import org.hibernate.boot.model.source.spi.MetadataSourceProcessor; import org.hibernate.boot.model.source.spi.MetadataSourceProcessor;
@ -40,16 +41,15 @@ public class HbmMetadataSourceProcessorImpl implements MetadataSourceProcessor {
this( managedResources.getXmlMappingBindings(), rootBuildingContext ); this( managedResources.getXmlMappingBindings(), rootBuildingContext );
} }
@SuppressWarnings("unchecked")
public HbmMetadataSourceProcessorImpl( public HbmMetadataSourceProcessorImpl(
Collection<Binding> xmlBindings, Collection<Binding<BindableMappingDescriptor>> xmlBindings,
MetadataBuildingContext rootBuildingContext) { MetadataBuildingContext rootBuildingContext) {
this.rootBuildingContext = rootBuildingContext; this.rootBuildingContext = rootBuildingContext;
final EntityHierarchyBuilder hierarchyBuilder = new EntityHierarchyBuilder(); final EntityHierarchyBuilder hierarchyBuilder = new EntityHierarchyBuilder();
this.mappingDocuments = new ArrayList<>(); this.mappingDocuments = new ArrayList<>();
for ( Binding xmlBinding : xmlBindings ) { for ( Binding<BindableMappingDescriptor> xmlBinding : xmlBindings ) {
if ( !(xmlBinding.getRoot() instanceof JaxbHbmHibernateMapping) ) { if ( !(xmlBinding.getRoot() instanceof JaxbHbmHibernateMapping) ) {
continue; continue;
} }

View File

@ -0,0 +1,26 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.mapping;
import java.util.List;
/**
* Commonality between {@link PersistentClass} and {@link MappedSuperclass},
* what JPA calls an {@linkplain jakarta.persistence.metamodel.IdentifiableType identifiable type}.
*
* @author Steve Ebersole
*/
public interface IdentifiableTypeClass extends TableContainer {
IdentifiableTypeClass getSuperType();
List<IdentifiableTypeClass> getSubTypes();
List<Property> getDeclaredProperties();
Table getImplicitTable();
void applyProperty(Property property);
}

View File

@ -17,18 +17,23 @@ import java.util.List;
* *
* @author Emmanuel Bernard * @author Emmanuel Bernard
*/ */
public class MappedSuperclass { public class MappedSuperclass implements IdentifiableTypeClass {
private final MappedSuperclass superMappedSuperclass; private final MappedSuperclass superMappedSuperclass;
private final PersistentClass superPersistentClass; private final PersistentClass superPersistentClass;
private final List<Property> declaredProperties; private final List<Property> declaredProperties;
private final Table implicitTable;
private Class<?> mappedClass; private Class<?> mappedClass;
private Property identifierProperty; private Property identifierProperty;
private Property version; private Property version;
private Component identifierMapper; private Component identifierMapper;
public MappedSuperclass(MappedSuperclass superMappedSuperclass, PersistentClass superPersistentClass) { public MappedSuperclass(
MappedSuperclass superMappedSuperclass,
PersistentClass superPersistentClass,
Table implicitTable) {
this.superMappedSuperclass = superMappedSuperclass; this.superMappedSuperclass = superMappedSuperclass;
this.superPersistentClass = superPersistentClass; this.superPersistentClass = superPersistentClass;
this.implicitTable = implicitTable;
this.declaredProperties = new ArrayList<>(); this.declaredProperties = new ArrayList<>();
} }
@ -205,4 +210,49 @@ public class MappedSuperclass {
public void prepareForMappingModel() { public void prepareForMappingModel() {
declaredProperties.sort( Comparator.comparing( Property::getName ) ); declaredProperties.sort( Comparator.comparing( Property::getName ) );
} }
@Override
public Table findTable(String name) {
return null;
}
@Override
public Table getTable(String name) {
return null;
}
@Override
public Join findSecondaryTable(String name) {
return null;
}
@Override
public Join getSecondaryTable(String name) {
return null;
}
@Override
public IdentifiableTypeClass getSuperType() {
if ( superPersistentClass != null ) {
return superPersistentClass;
}
return superMappedSuperclass;
}
@Override
public List<IdentifiableTypeClass> getSubTypes() {
throw new UnsupportedOperationException( "Not implemented yet" );
}
@Override
public Table getImplicitTable() {
return implicitTable;
}
@Override
public void applyProperty(Property property) {
assert property.getValue().getTable() != null;
assert property.getValue().getTable().equals( getImplicitTable() );
addDeclaredProperty( property );
}
} }

View File

@ -53,7 +53,7 @@ import static org.hibernate.sql.Template.collectColumnNames;
* *
* @author Gavin King * @author Gavin King
*/ */
public abstract class PersistentClass implements AttributeContainer, Serializable, Filterable, MetaAttributable, Contributable { public abstract class PersistentClass implements IdentifiableTypeClass, AttributeContainer, Filterable, MetaAttributable, Contributable, Serializable {
private static final Alias PK_ALIAS = new Alias( 15, "PK" ); private static final Alias PK_ALIAS = new Alias( 15, "PK" );
@ -1328,4 +1328,75 @@ public abstract class PersistentClass implements AttributeContainer, Serializabl
public List<CheckConstraint> getCheckConstraints() { public List<CheckConstraint> getCheckConstraints() {
return checkConstraints; return checkConstraints;
} }
public Table getImplicitTable() {
return getTable();
}
@Override
public Table findTable(String name) {
if ( getTable().getName().equals( name ) ) {
return getTable();
}
final Join secondaryTable = findSecondaryTable( name );
if ( secondaryTable != null ) {
return secondaryTable.getTable();
}
return null;
}
@Override
public Table getTable(String name) {
final Table table = findTable( name );
if ( table == null ) {
throw new MappingException( "Could not locate Table : " + name );
}
return table;
}
@Override
public Join findSecondaryTable(String name) {
for ( int i = 0; i < joins.size(); i++ ) {
final Join join = joins.get( i );
if ( join.getTable().getNameIdentifier().matches( name ) ) {
return join;
}
}
return null;
}
@Override
public Join getSecondaryTable(String name) {
final Join secondaryTable = findSecondaryTable( name );
if ( secondaryTable == null ) {
throw new MappingException( "Could not locate secondary Table : " + name );
}
return secondaryTable;
}
@Override
public IdentifiableTypeClass getSuperType() {
final PersistentClass superPersistentClass = getSuperclass();
if ( superPersistentClass != null ) {
return superPersistentClass;
}
return superMappedSuperclass;
}
@Override
public List<IdentifiableTypeClass> getSubTypes() {
throw new UnsupportedOperationException( "Not implemented yet" );
}
@Override
public void applyProperty(Property property) {
if ( property.getValue().getTable().equals( getImplicitTable() ) ) {
addProperty( property );
}
else {
final Join secondaryTable = getSecondaryTable( property.getValue().getTable().getName() );
secondaryTable.addProperty( property );
}
}
} }

View File

@ -0,0 +1,19 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.mapping;
/**
* Container for Table and Join reference
*
* @author Steve Ebersole
*/
public interface TableContainer {
Table findTable(String name);
Table getTable(String name);
Join findSecondaryTable(String name);
Join getSecondaryTable(String name);
}