HHH-16006 - Implement an "additional mapping" contributor SPI
This commit is contained in:
parent
863faf4c98
commit
a552a73632
|
@ -6,22 +6,28 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.boot.model.process.spi;
|
package org.hibernate.boot.model.process.spi;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import jakarta.persistence.AttributeConverter;
|
|
||||||
import org.hibernate.boot.MetadataSources;
|
import org.hibernate.boot.MetadataSources;
|
||||||
import org.hibernate.boot.internal.InFlightMetadataCollectorImpl;
|
import org.hibernate.boot.internal.InFlightMetadataCollectorImpl;
|
||||||
import org.hibernate.boot.internal.MetadataBuildingContextRootImpl;
|
import org.hibernate.boot.internal.MetadataBuildingContextRootImpl;
|
||||||
import org.hibernate.boot.jaxb.Origin;
|
import org.hibernate.boot.jaxb.Origin;
|
||||||
|
import org.hibernate.boot.jaxb.SourceType;
|
||||||
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmHibernateMapping;
|
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmHibernateMapping;
|
||||||
import org.hibernate.boot.jaxb.internal.MappingBinder;
|
import org.hibernate.boot.jaxb.internal.MappingBinder;
|
||||||
|
import org.hibernate.boot.jaxb.mapping.JaxbEntityMappings;
|
||||||
|
import org.hibernate.boot.jaxb.spi.BindableMappingDescriptor;
|
||||||
|
import org.hibernate.boot.jaxb.spi.Binding;
|
||||||
import org.hibernate.boot.model.TypeContributions;
|
import org.hibernate.boot.model.TypeContributions;
|
||||||
import org.hibernate.boot.model.TypeContributor;
|
import org.hibernate.boot.model.TypeContributor;
|
||||||
import org.hibernate.boot.model.convert.spi.ConverterRegistry;
|
import org.hibernate.boot.model.convert.spi.ConverterRegistry;
|
||||||
|
@ -52,7 +58,6 @@ import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||||
import org.hibernate.engine.config.spi.StandardConverters;
|
import org.hibernate.engine.config.spi.StandardConverters;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.BasicTypeRegistry;
|
import org.hibernate.type.BasicTypeRegistry;
|
||||||
|
@ -71,6 +76,8 @@ import org.hibernate.type.spi.TypeConfiguration;
|
||||||
import org.jboss.jandex.IndexView;
|
import org.jboss.jandex.IndexView;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import jakarta.persistence.AttributeConverter;
|
||||||
|
|
||||||
import static org.hibernate.internal.util.config.ConfigurationHelper.getPreferredSqlTypeCodeForArray;
|
import static org.hibernate.internal.util.config.ConfigurationHelper.getPreferredSqlTypeCodeForArray;
|
||||||
import static org.hibernate.internal.util.config.ConfigurationHelper.getPreferredSqlTypeCodeForDuration;
|
import static org.hibernate.internal.util.config.ConfigurationHelper.getPreferredSqlTypeCodeForDuration;
|
||||||
import static org.hibernate.internal.util.config.ConfigurationHelper.getPreferredSqlTypeCodeForInstant;
|
import static org.hibernate.internal.util.config.ConfigurationHelper.getPreferredSqlTypeCodeForInstant;
|
||||||
|
@ -333,14 +340,6 @@ public class MetadataBuildingProcess {
|
||||||
MetadataBuildingOptions options,
|
MetadataBuildingOptions options,
|
||||||
ClassLoaderService classLoaderService,
|
ClassLoaderService classLoaderService,
|
||||||
MetadataBuildingContextRootImpl rootMetadataBuildingContext) {
|
MetadataBuildingContextRootImpl rootMetadataBuildingContext) {
|
||||||
final EntityHierarchyBuilder hierarchyBuilder = new EntityHierarchyBuilder();
|
|
||||||
final AdditionalMappingContributionsImpl contributions = new AdditionalMappingContributionsImpl(
|
|
||||||
metadataCollector,
|
|
||||||
options,
|
|
||||||
rootMetadataBuildingContext,
|
|
||||||
hierarchyBuilder
|
|
||||||
);
|
|
||||||
|
|
||||||
final MappingBinder mappingBinder;
|
final MappingBinder mappingBinder;
|
||||||
if ( options.isXmlMappingEnabled() ) {
|
if ( options.isXmlMappingEnabled() ) {
|
||||||
mappingBinder = new MappingBinder(
|
mappingBinder = new MappingBinder(
|
||||||
|
@ -362,6 +361,13 @@ public class MetadataBuildingProcess {
|
||||||
mappingBinder = null;
|
mappingBinder = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final AdditionalMappingContributionsImpl contributions = new AdditionalMappingContributionsImpl(
|
||||||
|
metadataCollector,
|
||||||
|
options,
|
||||||
|
mappingBinder,
|
||||||
|
rootMetadataBuildingContext
|
||||||
|
);
|
||||||
|
|
||||||
final Collection<AdditionalMappingContributor> additionalMappingContributors = classLoaderService.loadJavaServices( AdditionalMappingContributor.class );
|
final Collection<AdditionalMappingContributor> additionalMappingContributors = classLoaderService.loadJavaServices( AdditionalMappingContributor.class );
|
||||||
additionalMappingContributors.forEach( (contributor) -> {
|
additionalMappingContributors.forEach( (contributor) -> {
|
||||||
contributions.setCurrentContributor( contributor.getContributorName() );
|
contributions.setCurrentContributor( contributor.getContributorName() );
|
||||||
|
@ -369,7 +375,7 @@ public class MetadataBuildingProcess {
|
||||||
contributor.contribute(
|
contributor.contribute(
|
||||||
contributions,
|
contributions,
|
||||||
metadataCollector,
|
metadataCollector,
|
||||||
mappingBinder,
|
classLoaderService,
|
||||||
rootMetadataBuildingContext
|
rootMetadataBuildingContext
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -378,28 +384,31 @@ public class MetadataBuildingProcess {
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
final ModelBinder binder = ModelBinder.prepare( rootMetadataBuildingContext );
|
contributions.complete();
|
||||||
for ( EntityHierarchySourceImpl entityHierarchySource : hierarchyBuilder.buildHierarchies() ) {
|
|
||||||
binder.bindEntityHierarchy( entityHierarchySource );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class AdditionalMappingContributionsImpl implements AdditionalMappingContributions {
|
private static class AdditionalMappingContributionsImpl implements AdditionalMappingContributions {
|
||||||
private final InFlightMetadataCollectorImpl metadataCollector;
|
private final InFlightMetadataCollectorImpl metadataCollector;
|
||||||
private final MetadataBuildingOptions options;
|
private final MetadataBuildingOptions options;
|
||||||
|
private final MappingBinder mappingBinder;
|
||||||
private final MetadataBuildingContextRootImpl rootMetadataBuildingContext;
|
private final MetadataBuildingContextRootImpl rootMetadataBuildingContext;
|
||||||
private final EntityHierarchyBuilder hierarchyBuilder;
|
private final EntityHierarchyBuilder hierarchyBuilder = new EntityHierarchyBuilder();
|
||||||
|
|
||||||
|
private List<Class<?>> additionalEntityClasses;
|
||||||
|
private List<JaxbEntityMappings> additionalJaxbMappings;
|
||||||
|
private boolean extraHbmXml = false;
|
||||||
|
|
||||||
private String currentContributor;
|
private String currentContributor;
|
||||||
|
|
||||||
public AdditionalMappingContributionsImpl(
|
public AdditionalMappingContributionsImpl(
|
||||||
InFlightMetadataCollectorImpl metadataCollector,
|
InFlightMetadataCollectorImpl metadataCollector,
|
||||||
MetadataBuildingOptions options,
|
MetadataBuildingOptions options,
|
||||||
MetadataBuildingContextRootImpl rootMetadataBuildingContext,
|
MappingBinder mappingBinder,
|
||||||
EntityHierarchyBuilder hierarchyBuilder) {
|
MetadataBuildingContextRootImpl rootMetadataBuildingContext) {
|
||||||
this.metadataCollector = metadataCollector;
|
this.metadataCollector = metadataCollector;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
this.mappingBinder = mappingBinder;
|
||||||
this.rootMetadataBuildingContext = rootMetadataBuildingContext;
|
this.rootMetadataBuildingContext = rootMetadataBuildingContext;
|
||||||
this.hierarchyBuilder = hierarchyBuilder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentContributor(String contributor) {
|
public void setCurrentContributor(String contributor) {
|
||||||
|
@ -407,22 +416,53 @@ public class MetadataBuildingProcess {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contributeBinding(JaxbHbmHibernateMapping hbmJaxbBinding, Origin origin) {
|
public void contributeEntity(Class<?> entityType) {
|
||||||
|
if ( additionalEntityClasses == null ) {
|
||||||
|
additionalEntityClasses = new ArrayList<>();
|
||||||
|
}
|
||||||
|
additionalEntityClasses.add( entityType );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contributeBinding(InputStream xmlStream) {
|
||||||
|
final Origin origin = new Origin( SourceType.INPUT_STREAM, null );
|
||||||
|
final Binding<BindableMappingDescriptor> binding = mappingBinder.bind( xmlStream, origin );
|
||||||
|
|
||||||
|
final BindableMappingDescriptor bindingRoot = binding.getRoot();
|
||||||
|
if ( bindingRoot instanceof JaxbHbmHibernateMapping ) {
|
||||||
|
contributeBinding( (JaxbHbmHibernateMapping) bindingRoot );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
contributeBinding( (JaxbEntityMappings) bindingRoot );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contributeBinding(JaxbEntityMappings mappingJaxbBinding) {
|
||||||
if ( ! options.isXmlMappingEnabled() ) {
|
if ( ! options.isXmlMappingEnabled() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hierarchyBuilder.indexMappingDocument( new MappingDocument(
|
if ( additionalJaxbMappings == null ) {
|
||||||
currentContributor,
|
additionalJaxbMappings = new ArrayList<>();
|
||||||
hbmJaxbBinding,
|
}
|
||||||
origin,
|
additionalJaxbMappings.add( mappingJaxbBinding );
|
||||||
rootMetadataBuildingContext
|
|
||||||
) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contributeEntity(PersistentClass entity) {
|
public void contributeBinding(JaxbHbmHibernateMapping hbmJaxbBinding) {
|
||||||
metadataCollector.addEntityBinding( entity );
|
if ( ! options.isXmlMappingEnabled() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
extraHbmXml = true;
|
||||||
|
|
||||||
|
hierarchyBuilder.indexMappingDocument( new MappingDocument(
|
||||||
|
currentContributor,
|
||||||
|
hbmJaxbBinding,
|
||||||
|
new Origin( SourceType.OTHER, null ),
|
||||||
|
rootMetadataBuildingContext
|
||||||
|
) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -448,6 +488,25 @@ public class MetadataBuildingProcess {
|
||||||
public void contributeAuxiliaryDatabaseObject(AuxiliaryDatabaseObject auxiliaryDatabaseObject) {
|
public void contributeAuxiliaryDatabaseObject(AuxiliaryDatabaseObject auxiliaryDatabaseObject) {
|
||||||
metadataCollector.addAuxiliaryDatabaseObject( auxiliaryDatabaseObject );
|
metadataCollector.addAuxiliaryDatabaseObject( auxiliaryDatabaseObject );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void complete() {
|
||||||
|
// annotations / orm.xml
|
||||||
|
if ( additionalEntityClasses != null || additionalJaxbMappings != null ) {
|
||||||
|
AnnotationMetadataSourceProcessorImpl.processAdditionalMappings(
|
||||||
|
additionalEntityClasses,
|
||||||
|
additionalJaxbMappings,
|
||||||
|
rootMetadataBuildingContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// hbm.xml
|
||||||
|
if ( extraHbmXml ) {
|
||||||
|
final ModelBinder binder = ModelBinder.prepare( rootMetadataBuildingContext );
|
||||||
|
for ( EntityHierarchySourceImpl entityHierarchySource : hierarchyBuilder.buildHierarchies() ) {
|
||||||
|
binder.bindEntityHierarchy( entityHierarchySource );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void processAdditionalJaxbMappingProducer(
|
private static void processAdditionalJaxbMappingProducer(
|
||||||
|
|
|
@ -9,7 +9,9 @@ package org.hibernate.boot.model.relational;
|
||||||
import org.hibernate.mapping.Contributable;
|
import org.hibernate.mapping.Contributable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contributable specialization for Tables and Sequences
|
* Database objects (table, sequence, etc) which are associated with
|
||||||
|
* a {@linkplain #getContributor() contributor} (ORM, Envers, etc) and
|
||||||
|
* can be selectively exported per contributor
|
||||||
*/
|
*/
|
||||||
public interface ContributableDatabaseObject extends Contributable, Exportable {
|
public interface ContributableDatabaseObject extends Contributable, Exportable {
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,9 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
|
||||||
private final List<XClass> xClasses = new ArrayList<>();
|
private final List<XClass> xClasses = new ArrayList<>();
|
||||||
private final ClassLoaderService classLoaderService;
|
private final ClassLoaderService classLoaderService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normal constructor used while processing {@linkplain org.hibernate.boot.MetadataSources mapping sources}
|
||||||
|
*/
|
||||||
public AnnotationMetadataSourceProcessorImpl(
|
public AnnotationMetadataSourceProcessorImpl(
|
||||||
ManagedResources managedResources,
|
ManagedResources managedResources,
|
||||||
final MetadataBuildingContextRootImpl rootMetadataBuildingContext,
|
final MetadataBuildingContextRootImpl rootMetadataBuildingContext,
|
||||||
|
@ -104,6 +107,54 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used as part of processing
|
||||||
|
* {@linkplain org.hibernate.boot.spi.AdditionalMappingContributions#contributeEntity(Class)} "additional" mappings}
|
||||||
|
*/
|
||||||
|
public static void processAdditionalMappings(
|
||||||
|
List<Class<?>> additionalClasses,
|
||||||
|
List<JaxbEntityMappings> additionalJaxbMappings,
|
||||||
|
MetadataBuildingContextRootImpl rootMetadataBuildingContext) {
|
||||||
|
final AnnotationMetadataSourceProcessorImpl processor = new AnnotationMetadataSourceProcessorImpl( rootMetadataBuildingContext );
|
||||||
|
|
||||||
|
if ( additionalJaxbMappings != null && rootMetadataBuildingContext.getBuildingOptions().isXmlMappingEnabled() ) {
|
||||||
|
final ConverterRegistry converterRegistry = rootMetadataBuildingContext.getMetadataCollector().getConverterRegistry();
|
||||||
|
final MetadataProviderInjector injector = (MetadataProviderInjector) processor.reflectionManager;
|
||||||
|
final JPAXMLOverriddenMetadataProvider metadataProvider = (JPAXMLOverriddenMetadataProvider) injector.getMetadataProvider();
|
||||||
|
|
||||||
|
for ( int i = 0; i < additionalJaxbMappings.size(); i++ ) {
|
||||||
|
final List<String> classNames = metadataProvider.getXMLContext().addDocument( additionalJaxbMappings.get( i ) );
|
||||||
|
for ( String className : classNames ) {
|
||||||
|
final XClass xClass = processor.toXClass( className, processor.reflectionManager, processor.classLoaderService );
|
||||||
|
processor.xClasses.add( xClass );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metadataProvider.getXMLContext().applyDiscoveredAttributeConverters( converterRegistry );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int i = 0; i < additionalClasses.size(); i++ ) {
|
||||||
|
final XClass xClass = processor.reflectionManager.toXClass( additionalClasses.get( i ) );
|
||||||
|
if ( !xClass.isAnnotationPresent( Entity.class ) ) {
|
||||||
|
log.debugf( "@Entity not found on additional entity class - `%s`" );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
processor.xClasses.add( xClass );
|
||||||
|
}
|
||||||
|
|
||||||
|
processor.processEntityHierarchies( new LinkedHashSet<>() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Form used from {@link #processAdditionalMappings}
|
||||||
|
*/
|
||||||
|
private AnnotationMetadataSourceProcessorImpl(MetadataBuildingContextRootImpl rootMetadataBuildingContext) {
|
||||||
|
this.rootMetadataBuildingContext = rootMetadataBuildingContext;
|
||||||
|
this.jandexView = null;
|
||||||
|
|
||||||
|
this.reflectionManager = rootMetadataBuildingContext.getBootstrapContext().getReflectionManager();
|
||||||
|
this.classLoaderService = rootMetadataBuildingContext.getBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class );
|
||||||
|
}
|
||||||
|
|
||||||
private void categorizeAnnotatedClass(Class<?> annotatedClass, ConverterRegistry converterRegistry) {
|
private void categorizeAnnotatedClass(Class<?> annotatedClass, ConverterRegistry converterRegistry) {
|
||||||
final XClass xClass = reflectionManager.toXClass( annotatedClass );
|
final XClass xClass = reflectionManager.toXClass( annotatedClass );
|
||||||
// categorize it, based on assumption it does not fall into multiple categories
|
// categorize it, based on assumption it does not fall into multiple categories
|
||||||
|
|
|
@ -6,30 +6,47 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.boot.spi;
|
package org.hibernate.boot.spi;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
import org.hibernate.Incubating;
|
import org.hibernate.Incubating;
|
||||||
import org.hibernate.boot.jaxb.Origin;
|
|
||||||
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmHibernateMapping;
|
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmHibernateMapping;
|
||||||
|
import org.hibernate.boot.jaxb.mapping.JaxbEntityMappings;
|
||||||
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
|
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
|
||||||
import org.hibernate.boot.model.relational.Sequence;
|
import org.hibernate.boot.model.relational.Sequence;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collector for contributions from {@linkplain AdditionalMappingContributor contributors}
|
* Collector for contributions from {@linkplain AdditionalMappingContributor contributors}
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
*
|
||||||
|
* @since 6.2
|
||||||
*/
|
*/
|
||||||
@Incubating
|
@Incubating
|
||||||
public interface AdditionalMappingContributions {
|
public interface AdditionalMappingContributions {
|
||||||
/**
|
/**
|
||||||
* Contribute mappings in the form of {@code hbm.xml} JAXB bindings
|
* Contribute a presumably annotated entity class.
|
||||||
*/
|
*/
|
||||||
void contributeBinding(JaxbHbmHibernateMapping hbmJaxbBinding, Origin origin);
|
void contributeEntity(Class<?> entityType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contribute a materialized PersistentClass
|
* Contribute mappings from the InputStream containing an XML mapping document.
|
||||||
*/
|
*/
|
||||||
void contributeEntity(PersistentClass entity);
|
void contributeBinding(InputStream xmlStream);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contribute mappings in the form of {@code hbm.xml} JAXB bindings.
|
||||||
|
*
|
||||||
|
* @deprecated {@code hbm.xml} mapping file support is deprecated. Use
|
||||||
|
* {@linkplain #contributeBinding(JaxbEntityMappings) extended orm.xml}
|
||||||
|
* bindings instead.
|
||||||
|
*/
|
||||||
|
void contributeBinding(JaxbHbmHibernateMapping hbmJaxbBinding);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contribute mappings in the form of (extended) {@code orm.xml} JAXB bindings
|
||||||
|
*/
|
||||||
|
void contributeBinding(JaxbEntityMappings mappingJaxbBinding);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contribute a materialized Table
|
* Contribute a materialized Table
|
||||||
|
|
|
@ -7,11 +7,10 @@
|
||||||
package org.hibernate.boot.spi;
|
package org.hibernate.boot.spi;
|
||||||
|
|
||||||
import org.hibernate.Incubating;
|
import org.hibernate.Incubating;
|
||||||
import org.hibernate.boot.jaxb.internal.MappingBinder;
|
import org.hibernate.boot.ResourceStreamLocator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contract allowing pluggable contributions of additional
|
* Contract allowing pluggable contributions of additional mapping objects.
|
||||||
* mapping objects.
|
|
||||||
*
|
*
|
||||||
* Resolvable as a {@linkplain java.util.ServiceLoader Java service}.
|
* Resolvable as a {@linkplain java.util.ServiceLoader Java service}.
|
||||||
*
|
*
|
||||||
|
@ -20,7 +19,9 @@ import org.hibernate.boot.jaxb.internal.MappingBinder;
|
||||||
@Incubating
|
@Incubating
|
||||||
public interface AdditionalMappingContributor {
|
public interface AdditionalMappingContributor {
|
||||||
/**
|
/**
|
||||||
* The name of this contributor.
|
* The name of this contributor. May be {@code null}.
|
||||||
|
*
|
||||||
|
* @see org.hibernate.mapping.Contributable
|
||||||
*/
|
*/
|
||||||
default String getContributorName() {
|
default String getContributorName() {
|
||||||
return null;
|
return null;
|
||||||
|
@ -29,15 +30,14 @@ public interface AdditionalMappingContributor {
|
||||||
/**
|
/**
|
||||||
* Contribute the additional mappings
|
* Contribute the additional mappings
|
||||||
*
|
*
|
||||||
* @param contributions Collector of the contributions
|
* @param contributions Collector of the contributions.
|
||||||
* @param metadata Current (live) metadata
|
* @param metadata Current (live) metadata. Can be used to access already known mappings.
|
||||||
* @param jaxbBinder JAXB binding support for XML documents. May be {@code null}
|
* @param resourceStreamLocator Delegate for locating XML resources via class-path lookup.
|
||||||
* if XML processing is {@linkplain MetadataBuildingOptions#isXmlMappingEnabled() disabled}
|
* @param buildingContext Access to useful contextual references.
|
||||||
* @param buildingContext Access to useful contextual details
|
|
||||||
*/
|
*/
|
||||||
void contribute(
|
void contribute(
|
||||||
AdditionalMappingContributions contributions,
|
AdditionalMappingContributions contributions,
|
||||||
InFlightMetadataCollector metadata,
|
InFlightMetadataCollector metadata,
|
||||||
MappingBinder jaxbBinder,
|
ResourceStreamLocator resourceStreamLocator,
|
||||||
MetadataBuildingContext buildingContext);
|
MetadataBuildingContext buildingContext);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,20 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.mapping;
|
package org.hibernate.mapping;
|
||||||
|
|
||||||
|
import org.hibernate.boot.model.relational.ContributableDatabaseObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Part of the mapping model that is associated with a contributor.
|
* Parts of the mapping model which are associated with a
|
||||||
* ORM, Envers, Search, etc
|
* {@linkplain #getContributor() contributor} (ORM, Envers, etc).
|
||||||
|
* <p/>
|
||||||
|
* The most useful aspect of this is the {@link ContributableDatabaseObject}
|
||||||
|
* specialization.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface Contributable {
|
public interface Contributable {
|
||||||
|
/**
|
||||||
|
* The name of the contributor which contributed this
|
||||||
|
*/
|
||||||
String getContributor();
|
String getContributor();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,185 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.intg;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.boot.ResourceStreamLocator;
|
||||||
|
import org.hibernate.boot.spi.AdditionalMappingContributions;
|
||||||
|
import org.hibernate.boot.spi.AdditionalMappingContributor;
|
||||||
|
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
||||||
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.BootstrapServiceRegistry;
|
||||||
|
import org.hibernate.testing.orm.junit.BootstrapServiceRegistry.JavaService;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModelScope;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import jakarta.persistence.Basic;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*
|
||||||
|
* @implNote hibernate-envers is already a full testing of contributing a {@code hbm.xml}
|
||||||
|
* document; so we skip that here until if/when we transition it to use a better approach
|
||||||
|
*/
|
||||||
|
@BootstrapServiceRegistry(
|
||||||
|
javaServices = @JavaService(
|
||||||
|
role = AdditionalMappingContributor.class,
|
||||||
|
impl = AdditionalMappingContributorTests.AdditionalMappingContributorImpl.class
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@DomainModel( annotatedClasses = AdditionalMappingContributorTests.Entity1.class )
|
||||||
|
@SessionFactory
|
||||||
|
public class AdditionalMappingContributorTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void verifyClassContribution(DomainModelScope domainModelScope, SessionFactoryScope sessionFactoryScope) {
|
||||||
|
final PersistentClass binding = domainModelScope.getDomainModel().getEntityBinding( Entity2.class.getName() );
|
||||||
|
assertThat( binding ).isNotNull();
|
||||||
|
assertThat( binding.getIdentifierProperty() ).isNotNull();
|
||||||
|
assertThat( binding.getProperties() ).hasSize( 1 );
|
||||||
|
|
||||||
|
sessionFactoryScope.inTransaction( (session) -> {
|
||||||
|
final List<?> results = session.createSelectionQuery( "from Entity2" ).list();
|
||||||
|
assertThat( results ).hasSize( 0 );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void verifyOrmXmlContribution(DomainModelScope domainModelScope, SessionFactoryScope sessionFactoryScope) {
|
||||||
|
final PersistentClass binding = domainModelScope.getDomainModel().getEntityBinding( Entity3.class.getName() );
|
||||||
|
assertThat( binding ).isNotNull();
|
||||||
|
assertThat( binding.getIdentifierProperty() ).isNotNull();
|
||||||
|
assertThat( binding.getProperties() ).hasSize( 1 );
|
||||||
|
|
||||||
|
sessionFactoryScope.inTransaction( (session) -> {
|
||||||
|
final List<?> results = session.createSelectionQuery( "from Entity3" ).list();
|
||||||
|
assertThat( results ).hasSize( 0 );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "Entity1" )
|
||||||
|
@Table( name = "Entity1" )
|
||||||
|
public static class Entity1 {
|
||||||
|
@Id
|
||||||
|
private Integer id;
|
||||||
|
@Basic
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private Entity1() {
|
||||||
|
// for use by Hibernate
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entity1(Integer id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Entity( name = "Entity2" )
|
||||||
|
@Table( name = "Entity2" )
|
||||||
|
public static class Entity2 {
|
||||||
|
@Id
|
||||||
|
private Integer id;
|
||||||
|
@Basic
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private Entity2() {
|
||||||
|
// for use by Hibernate
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entity2(Integer id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "Entity3" )
|
||||||
|
@Table( name = "Entity3" )
|
||||||
|
public static class Entity3 {
|
||||||
|
@Id
|
||||||
|
private Integer id;
|
||||||
|
@Basic
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private Entity3() {
|
||||||
|
// for use by Hibernate
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entity3(Integer id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AdditionalMappingContributorImpl implements AdditionalMappingContributor {
|
||||||
|
@Override
|
||||||
|
public void contribute(
|
||||||
|
AdditionalMappingContributions contributions,
|
||||||
|
InFlightMetadataCollector metadata,
|
||||||
|
ResourceStreamLocator resourceStreamLocator,
|
||||||
|
MetadataBuildingContext buildingContext) {
|
||||||
|
contributions.contributeEntity( Entity2.class );
|
||||||
|
|
||||||
|
try ( final InputStream stream = resourceStreamLocator.locateResourceStream( "mappings/intg/contributed-mapping.xml" ) ) {
|
||||||
|
contributions.contributeBinding( stream );
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
throw new RuntimeException( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
<entity-mappings xmlns="http://www.hibernate.org/xsd/orm/mapping" version="3.1">
|
||||||
|
<entity class="org.hibernate.orm.test.intg.AdditionalMappingContributorTests$Entity3">
|
||||||
|
<attributes>
|
||||||
|
<id name="id"/>
|
||||||
|
<basic name="name"/>
|
||||||
|
</attributes>
|
||||||
|
</entity>
|
||||||
|
</entity-mappings>
|
|
@ -7,16 +7,12 @@
|
||||||
package org.hibernate.envers.boot.internal;
|
package org.hibernate.envers.boot.internal;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.boot.jaxb.Origin;
|
import org.hibernate.boot.ResourceStreamLocator;
|
||||||
import org.hibernate.boot.jaxb.SourceType;
|
|
||||||
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmHibernateMapping;
|
|
||||||
import org.hibernate.boot.jaxb.internal.MappingBinder;
|
|
||||||
import org.hibernate.boot.spi.AdditionalMappingContributions;
|
import org.hibernate.boot.spi.AdditionalMappingContributions;
|
||||||
import org.hibernate.boot.spi.AdditionalMappingContributor;
|
import org.hibernate.boot.spi.AdditionalMappingContributor;
|
||||||
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
||||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
import org.hibernate.boot.spi.MetadataBuildingOptions;
|
import org.hibernate.boot.spi.MetadataBuildingOptions;
|
||||||
import org.hibernate.envers.configuration.internal.MappingCollector;
|
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
|
||||||
import static org.hibernate.cfg.AvailableSettings.XML_MAPPING_ENABLED;
|
import static org.hibernate.cfg.AvailableSettings.XML_MAPPING_ENABLED;
|
||||||
|
@ -34,7 +30,7 @@ public class AdditionalMappingContributorImpl implements AdditionalMappingContri
|
||||||
public void contribute(
|
public void contribute(
|
||||||
AdditionalMappingContributions contributions,
|
AdditionalMappingContributions contributions,
|
||||||
InFlightMetadataCollector metadata,
|
InFlightMetadataCollector metadata,
|
||||||
MappingBinder jaxbBinder,
|
ResourceStreamLocator resourceStreamLocator,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
final MetadataBuildingOptions metadataBuildingOptions = metadata.getMetadataBuildingOptions();
|
final MetadataBuildingOptions metadataBuildingOptions = metadata.getMetadataBuildingOptions();
|
||||||
final ServiceRegistry serviceRegistry = metadataBuildingOptions.getServiceRegistry();
|
final ServiceRegistry serviceRegistry = metadataBuildingOptions.getServiceRegistry();
|
||||||
|
@ -51,15 +47,6 @@ public class AdditionalMappingContributorImpl implements AdditionalMappingContri
|
||||||
+ "`; alternatively disable Hibernate Envers." );
|
+ "`; alternatively disable Hibernate Envers." );
|
||||||
}
|
}
|
||||||
|
|
||||||
final MappingCollector mappingCollector = new MappingCollector() {
|
enversService.initialize( metadata, contributions::contributeBinding );
|
||||||
private final Origin origin = new Origin( SourceType.OTHER, "envers" );
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addDocument(JaxbHbmHibernateMapping mapping) {
|
|
||||||
contributions.contributeBinding( mapping, origin );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
enversService.initialize( metadata, mappingCollector );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue