diff --git a/hibernate-core/src/main/java/org/hibernate/boot/MetadataSources.java b/hibernate-core/src/main/java/org/hibernate/boot/MetadataSources.java index afef29c54a..2247a6e30f 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/MetadataSources.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/MetadataSources.java @@ -23,6 +23,7 @@ import org.hibernate.Internal; import org.hibernate.boot.archive.spi.InputStreamAccess; import org.hibernate.boot.internal.MetadataBuilderImpl; 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.XmlSource; import org.hibernate.boot.registry.BootstrapServiceRegistry; @@ -64,7 +65,7 @@ public class MetadataSources implements Serializable { private XmlMappingBinderAccess xmlMappingBinderAccess; - private List> xmlBindings; + private List> xmlBindings; private LinkedHashSet> annotatedClasses; private LinkedHashSet annotatedClassNames; private LinkedHashSet annotatedPackages; @@ -120,7 +121,7 @@ public class MetadataSources implements Serializable { return xmlMappingBinderAccess; } - public List> getXmlBindings() { + public List> getXmlBindings() { return xmlBindings == null ? Collections.emptyList() : xmlBindings; } @@ -371,7 +372,8 @@ public class MetadataSources implements Serializable { * @return this (for method chaining purposes) */ public MetadataSources addXmlBinding(Binding binding) { - getXmlBindingsForWrite().add( binding ); + //noinspection unchecked + getXmlBindingsForWrite().add( (Binding) binding ); return this; } @@ -547,7 +549,7 @@ public class MetadataSources implements Serializable { return this; } - private List> getXmlBindingsForWrite() { + private List> getXmlBindingsForWrite() { if ( xmlBindings == null ) { xmlBindings = new ArrayList<>(); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java index 4cb4cb58b0..e7aa80dde7 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java @@ -513,6 +513,10 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector, return this; } + public AttributeConverterManager getAttributeConverterManager() { + return attributeConverterManager; + } + @Override public void addAttributeConverter(Class> converterClass) { attributeConverterManager.addConverter( diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/AttributeConverterManager.java b/hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/AttributeConverterManager.java index 4bd0d1db01..6ed149248d 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/AttributeConverterManager.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/AttributeConverterManager.java @@ -46,6 +46,13 @@ public class AttributeConverterManager implements ConverterAutoApplyHandler { private Map, ConverterDescriptor> attributeConverterDescriptorsByClass; private Map, RegisteredConversion> registeredConversionsByDomainType; + public RegisteredConversion findRegisteredConversion(Class domainType) { + if ( registeredConversionsByDomainType == null ) { + return null; + } + return registeredConversionsByDomainType.get( domainType ); + } + public void addConverter(ConverterDescriptor descriptor) { if ( log.isTraceEnabled() ) { log.tracef( "Starting AttributeConverterManager#addConverter : `%s`", diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/InheritanceState.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/InheritanceState.java index b5e5ad6296..d868d9f065 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/InheritanceState.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/InheritanceState.java @@ -317,7 +317,7 @@ public class InheritanceState { //add MappedSuperclass if not already there mappedSuperclass = buildingContext.getMetadataCollector().getMappedSuperclass( type ); if ( mappedSuperclass == null ) { - mappedSuperclass = new org.hibernate.mapping.MappedSuperclass( parentSuperclass, superEntity ); + mappedSuperclass = new org.hibernate.mapping.MappedSuperclass( parentSuperclass, superEntity, persistentClass.getImplicitTable() ); mappedSuperclass.setMappedClass( type ); buildingContext.getMetadataCollector().addMappedSuperclass( type, mappedSuperclass ); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/naming/Identifier.java b/hibernate-core/src/main/java/org/hibernate/boot/model/naming/Identifier.java index 953a851fd2..64cada3ed3 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/naming/Identifier.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/naming/Identifier.java @@ -242,6 +242,12 @@ public class Identifier implements Comparable { return getCanonicalName().equals( that.getCanonicalName() ); } + public boolean matches(String name) { + return isQuoted() + ? text.equals( name ) + : text.equalsIgnoreCase( name ); + } + @Override public int hashCode() { return isQuoted ? text.hashCode() : text.toLowerCase( Locale.ENGLISH ).hashCode(); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/ManagedResourcesImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/ManagedResourcesImpl.java index 0f230942c6..5a83268943 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/ManagedResourcesImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/ManagedResourcesImpl.java @@ -17,20 +17,23 @@ import java.util.Set; import org.hibernate.Internal; import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.jaxb.spi.BindableMappingDescriptor; import org.hibernate.boot.jaxb.spi.Binding; import org.hibernate.boot.model.convert.spi.ConverterDescriptor; import org.hibernate.boot.model.process.spi.ManagedResources; import org.hibernate.boot.spi.BootstrapContext; +import jakarta.persistence.AttributeConverter; + /** * @author Steve Ebersole */ public class ManagedResourcesImpl implements ManagedResources { - private Map attributeConverterDescriptorMap = new HashMap<>(); - private Set annotatedClassReferences = new LinkedHashSet<>(); - private Set annotatedClassNames = new LinkedHashSet<>(); - private Set annotatedPackageNames = new LinkedHashSet<>(); - private List mappingFileBindings = new ArrayList<>(); + private final Map, ConverterDescriptor> attributeConverterDescriptorMap = new HashMap<>(); + private final Set> annotatedClassReferences = new LinkedHashSet<>(); + private final Set annotatedClassNames = new LinkedHashSet<>(); + private final Set annotatedPackageNames = new LinkedHashSet<>(); + private final List> mappingFileBindings = new ArrayList<>(); private Map> extraQueryImports; public static ManagedResourcesImpl baseline(MetadataSources sources, BootstrapContext bootstrapContext) { @@ -44,7 +47,7 @@ public class ManagedResourcesImpl implements ManagedResources { return impl; } - private ManagedResourcesImpl() { + public ManagedResourcesImpl() { } @Override @@ -53,7 +56,7 @@ public class ManagedResourcesImpl implements ManagedResources { } @Override - public Collection getAnnotatedClassReferences() { + public Collection> getAnnotatedClassReferences() { return Collections.unmodifiableSet( annotatedClassReferences ); } @@ -68,7 +71,7 @@ public class ManagedResourcesImpl implements ManagedResources { } @Override - public Collection getXmlMappingBindings() { + public Collection> getXmlMappingBindings() { return Collections.unmodifiableList( mappingFileBindings ); } @@ -87,7 +90,7 @@ public class ManagedResourcesImpl implements ManagedResources { } @Internal - public void addAnnotatedClassReference(Class annotatedClassReference) { + public void addAnnotatedClassReference(Class annotatedClassReference) { annotatedClassReferences.add( annotatedClassReference ); } @@ -102,7 +105,7 @@ public class ManagedResourcesImpl implements ManagedResources { } @Internal - public void addXmlBinding(Binding binding) { + public void addXmlBinding(Binding binding) { mappingFileBindings.add( binding ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/ManagedResources.java b/hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/ManagedResources.java index 419c29f352..a27a39a729 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/ManagedResources.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/ManagedResources.java @@ -9,6 +9,7 @@ package org.hibernate.boot.model.process.spi; import java.util.Collection; import java.util.Map; +import org.hibernate.boot.jaxb.spi.BindableMappingDescriptor; import org.hibernate.boot.jaxb.spi.Binding; 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. */ - Collection getAnnotatedClassReferences(); + Collection> getAnnotatedClassReferences(); /** * 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. */ - Collection getXmlMappingBindings(); + Collection> getXmlMappingBindings(); Map> getExtraQueryImports(); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/HbmMetadataSourceProcessorImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/HbmMetadataSourceProcessorImpl.java index 2ebcb4f687..a092d600e6 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/HbmMetadataSourceProcessorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/HbmMetadataSourceProcessorImpl.java @@ -12,6 +12,7 @@ import java.util.List; import java.util.Set; 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.model.process.spi.ManagedResources; import org.hibernate.boot.model.source.spi.MetadataSourceProcessor; @@ -40,16 +41,15 @@ public class HbmMetadataSourceProcessorImpl implements MetadataSourceProcessor { this( managedResources.getXmlMappingBindings(), rootBuildingContext ); } - @SuppressWarnings("unchecked") public HbmMetadataSourceProcessorImpl( - Collection xmlBindings, + Collection> xmlBindings, MetadataBuildingContext rootBuildingContext) { this.rootBuildingContext = rootBuildingContext; final EntityHierarchyBuilder hierarchyBuilder = new EntityHierarchyBuilder(); this.mappingDocuments = new ArrayList<>(); - for ( Binding xmlBinding : xmlBindings ) { + for ( Binding xmlBinding : xmlBindings ) { if ( !(xmlBinding.getRoot() instanceof JaxbHbmHibernateMapping) ) { continue; } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/IdentifiableTypeClass.java b/hibernate-core/src/main/java/org/hibernate/mapping/IdentifiableTypeClass.java new file mode 100644 index 0000000000..77c0dc5519 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/mapping/IdentifiableTypeClass.java @@ -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 getSubTypes(); + + List getDeclaredProperties(); + + Table getImplicitTable(); + + void applyProperty(Property property); +} diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/MappedSuperclass.java b/hibernate-core/src/main/java/org/hibernate/mapping/MappedSuperclass.java index 75ec6c032c..d437c5a5c6 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/MappedSuperclass.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/MappedSuperclass.java @@ -17,18 +17,23 @@ import java.util.List; * * @author Emmanuel Bernard */ -public class MappedSuperclass { +public class MappedSuperclass implements IdentifiableTypeClass { private final MappedSuperclass superMappedSuperclass; private final PersistentClass superPersistentClass; private final List declaredProperties; + private final Table implicitTable; private Class mappedClass; private Property identifierProperty; private Property version; private Component identifierMapper; - public MappedSuperclass(MappedSuperclass superMappedSuperclass, PersistentClass superPersistentClass) { + public MappedSuperclass( + MappedSuperclass superMappedSuperclass, + PersistentClass superPersistentClass, + Table implicitTable) { this.superMappedSuperclass = superMappedSuperclass; this.superPersistentClass = superPersistentClass; + this.implicitTable = implicitTable; this.declaredProperties = new ArrayList<>(); } @@ -205,4 +210,49 @@ public class MappedSuperclass { public void prepareForMappingModel() { 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 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 ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java b/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java index fe6b2ae082..32982f71e5 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/PersistentClass.java @@ -53,7 +53,7 @@ import static org.hibernate.sql.Template.collectColumnNames; * * @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" ); @@ -1328,4 +1328,75 @@ public abstract class PersistentClass implements AttributeContainer, Serializabl public List getCheckConstraints() { 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 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 ); + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/TableContainer.java b/hibernate-core/src/main/java/org/hibernate/mapping/TableContainer.java new file mode 100644 index 0000000000..1ef6d16ee5 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/mapping/TableContainer.java @@ -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); +}