HHH-18520 Fix issue with dynamic model

This commit is contained in:
Andrea Boriero 2024-08-28 16:33:06 +02:00 committed by Steve Ebersole
parent 92c434dd9b
commit 53f9321cc0
5 changed files with 159 additions and 26 deletions

View File

@ -8,6 +8,7 @@ package org.hibernate.boot.model.internal;
import org.hibernate.MappingException;
import org.hibernate.annotations.Target;
import org.hibernate.boot.models.internal.ModelsHelper;
import org.hibernate.boot.spi.AccessType;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.PropertyData;
@ -87,8 +88,11 @@ public class PropertyInferredData implements PropertyData {
if ( targetAnnotation != null ) {
final String targetName = targetAnnotation.value();
final SourceModelBuildingContext sourceModelBuildingContext = sourceModelContext;
final ClassDetails classDetails = sourceModelBuildingContext.getClassDetailsRegistry()
.resolveClassDetails( targetName );
final ClassDetails classDetails = ModelsHelper.resolveClassDetails(
targetName,
sourceModelBuildingContext.getClassDetailsRegistry(),
() -> new DynamicClassDetails( targetName, sourceModelContext )
);
return new ClassTypeDetailsImpl( classDetails, TypeDetails.Kind.CLASS );
}
@ -117,8 +121,11 @@ public class PropertyInferredData implements PropertyData {
final org.hibernate.boot.internal.Target annotationUsage = propertyMember.getDirectAnnotationUsage( org.hibernate.boot.internal.Target.class );
if ( annotationUsage != null ) {
final String targetName = annotationUsage.value();
final ClassDetails classDetails = sourceModelBuildingContext.getClassDetailsRegistry()
.resolveClassDetails( targetName );
final ClassDetails classDetails = ModelsHelper.resolveClassDetails(
targetName,
sourceModelBuildingContext.getClassDetailsRegistry(),
() -> new DynamicClassDetails( targetName, sourceModelBuildingContext )
);
return new ClassTypeDetailsImpl( classDetails, TypeDetails.Kind.CLASS );
}
@ -169,4 +176,6 @@ public class PropertyInferredData implements PropertyData {
public ClassDetails getDeclaringClass() {
return declaringClass;
}
}

View File

@ -6,10 +6,15 @@
*/
package org.hibernate.boot.models.internal;
import java.util.function.Supplier;
import org.hibernate.annotations.TenantId;
import org.hibernate.models.internal.MutableClassDetailsRegistry;
import org.hibernate.models.internal.jdk.JdkBuilders;
import org.hibernate.models.jandex.internal.JandexClassDetails;
import org.hibernate.models.jandex.spi.JandexModelBuildingContext;
import org.hibernate.models.spi.AnnotationDescriptorRegistry;
import org.hibernate.models.spi.ClassDetails;
import org.hibernate.models.spi.ClassDetailsRegistry;
import org.hibernate.models.spi.RegistryPrimer;
import org.hibernate.models.spi.SourceModelBuildingContext;
@ -51,8 +56,26 @@ public class ModelsHelper {
);
}
classDetailsRegistry.resolveClassDetails( className );
resolveClassDetails(
className,
classDetailsRegistry,
() -> new JandexClassDetails( knownClass, buildingContext )
);
}
}
}
public static ClassDetails resolveClassDetails(
String className,
ClassDetailsRegistry classDetailsRegistry,
Supplier<ClassDetails> classDetailsSupplier) {
ClassDetails classDetails = classDetailsRegistry.findClassDetails( className );
if ( classDetails != null ) {
return classDetails;
}
classDetails = classDetailsSupplier.get();
classDetailsRegistry.as( MutableClassDetailsRegistry.class )
.addClassDetails( className, classDetails );
return classDetails;
}
}

View File

@ -32,6 +32,7 @@ import org.hibernate.boot.models.annotations.internal.AttributeAccessorAnnotatio
import org.hibernate.boot.models.annotations.internal.CacheAnnotation;
import org.hibernate.boot.models.annotations.internal.CacheableJpaAnnotation;
import org.hibernate.boot.models.annotations.internal.ExtendsXmlAnnotation;
import org.hibernate.boot.models.internal.ModelsHelper;
import org.hibernate.boot.models.xml.internal.attr.BasicAttributeProcessing;
import org.hibernate.boot.models.xml.internal.attr.BasicIdAttributeProcessing;
import org.hibernate.boot.models.xml.internal.attr.CommonAttributeProcessing;
@ -100,7 +101,19 @@ public class ManagedTypeProcessor {
memberAdjuster = ManagedTypeProcessor::adjustDynamicTypeMember;
classAccessType = AccessType.FIELD;
classDetails = (MutableClassDetails) classDetailsRegistry.resolveClassDetails( jaxbEntity.getName() );
classDetails = (MutableClassDetails) ModelsHelper.resolveClassDetails(
jaxbEntity.getName(),
classDetailsRegistry,
() ->
new DynamicClassDetails(
jaxbEntity.getName(),
null,
false,
null,
null,
xmlDocumentContext.getModelBuildingContext()
)
);
prepareDynamicClass( classDetails, jaxbEntity, xmlDocumentContext );
}
@ -934,8 +947,15 @@ public class ManagedTypeProcessor {
throw new ModelsException( "Embeddable did not define class nor name" );
}
// no class == dynamic...
classDetails = (MutableClassDetails) classDetailsRegistry
.resolveClassDetails( jaxbEmbeddable.getName() );
classDetails = (MutableClassDetails) ModelsHelper.resolveClassDetails(
jaxbEmbeddable.getName(),
classDetailsRegistry,
() ->
new DynamicClassDetails(
jaxbEmbeddable.getName(),
xmlDocumentContext.getModelBuildingContext()
)
);
classAccessType = AccessType.FIELD;
memberAdjuster = ManagedTypeProcessor::adjustDynamicTypeMember;

View File

@ -20,6 +20,7 @@ import org.hibernate.boot.jaxb.mapping.spi.JaxbEmbeddedMapping;
import org.hibernate.boot.jaxb.mapping.spi.JaxbPersistentAttribute;
import org.hibernate.boot.jaxb.mapping.spi.JaxbPluralAttribute;
import org.hibernate.boot.jaxb.mapping.spi.JaxbUserTypeImpl;
import org.hibernate.boot.models.internal.ModelsHelper;
import org.hibernate.boot.models.xml.internal.XmlAnnotationHelper;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.EffectiveMappingDefaults;
@ -137,8 +138,11 @@ public interface XmlDocumentContext {
// <embedded/>, <embedded-id/>
final String target = jaxbEmbeddedMapping.getTarget();
if ( isNotEmpty( target ) ) {
return (MutableClassDetails) getModelBuildingContext().getClassDetailsRegistry()
.resolveClassDetails( target );
return (MutableClassDetails) ModelsHelper.resolveClassDetails(
target,
getModelBuildingContext().getClassDetailsRegistry(),
() -> new DynamicClassDetails( target, getModelBuildingContext() )
);
}
// fall through to exception
}
@ -146,8 +150,18 @@ public interface XmlDocumentContext {
if ( jaxbPersistentAttribute instanceof JaxbAssociationAttribute jaxbAssociationAttribute ) {
final String target = jaxbAssociationAttribute.getTargetEntity();
if ( isNotEmpty( target ) ) {
return (MutableClassDetails) getModelBuildingContext().getClassDetailsRegistry()
.resolveClassDetails( target );
return (MutableClassDetails) ModelsHelper.resolveClassDetails(
target,
getModelBuildingContext().getClassDetailsRegistry(),
() -> new DynamicClassDetails(
target,
null,
false,
null,
null,
getModelBuildingContext()
)
);
}
// fall through to exception
}

View File

@ -11,13 +11,22 @@ import java.io.InputStream;
import java.util.List;
import org.hibernate.boot.ResourceStreamLocator;
import org.hibernate.boot.models.HibernateAnnotations;
import org.hibernate.boot.models.JpaAnnotations;
import org.hibernate.boot.models.annotations.internal.EntityJpaAnnotation;
import org.hibernate.boot.models.internal.ModelsHelper;
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.models.internal.dynamic.DynamicClassDetails;
import org.hibernate.models.internal.dynamic.DynamicFieldDetails;
import org.hibernate.models.internal.jdk.JdkClassDetails;
import org.hibernate.models.spi.ClassDetails;
import org.hibernate.models.spi.ClassDetailsRegistry;
import org.hibernate.models.spi.MutableMemberDetails;
import org.hibernate.models.spi.SourceModelBuildingContext;
import org.hibernate.testing.orm.junit.BootstrapServiceRegistry;
import org.hibernate.testing.orm.junit.BootstrapServiceRegistry.JavaService;
@ -292,28 +301,53 @@ public class AdditionalMappingContributorTests {
InFlightMetadataCollector metadata,
ResourceStreamLocator resourceStreamLocator,
MetadataBuildingContext buildingContext) {
final ClassDetailsRegistry classDetailsRegistry = buildingContext.getMetadataCollector()
.getSourceModelBuildingContext()
SourceModelBuildingContext sourceModelBuildingContext = buildingContext.getMetadataCollector()
.getSourceModelBuildingContext();
final ClassDetailsRegistry classDetailsRegistry = sourceModelBuildingContext
.getClassDetailsRegistry();
contributeEntity4Details( contributions, classDetailsRegistry );
contributeEntity5Details( contributions, classDetailsRegistry );
contributeEntity4Details( contributions, sourceModelBuildingContext, classDetailsRegistry );
contributeEntity5Details( contributions, sourceModelBuildingContext, classDetailsRegistry );
}
private static void contributeEntity4Details(
AdditionalMappingContributions contributions,
SourceModelBuildingContext sourceModelBuildingContext,
ClassDetailsRegistry classDetailsRegistry) {
final ClassDetails entity4Details = classDetailsRegistry.resolveClassDetails(
Entity4.class.getName()
final ClassDetails entity4Details = ModelsHelper.resolveClassDetails(
Entity4.class.getName(),
classDetailsRegistry,
() ->
new JdkClassDetails( Entity4.class, sourceModelBuildingContext )
);
contributions.contributeManagedClass( entity4Details );
}
private static void contributeEntity5Details(
AdditionalMappingContributions contributions,
SourceModelBuildingContext modelBuildingContext,
ClassDetailsRegistry classDetailsRegistry) {
final ClassDetails entity5Details = classDetailsRegistry.resolveClassDetails(
Entity5.class.getName()
final ClassDetails entity5Details = ModelsHelper.resolveClassDetails(
Entity5.class.getName(),
classDetailsRegistry,
() -> {
final JdkClassDetails jdkClassDetails = new JdkClassDetails(
Entity5.class,
modelBuildingContext
);
final EntityJpaAnnotation entityUsage = (EntityJpaAnnotation) jdkClassDetails.applyAnnotationUsage(
JpaAnnotations.ENTITY,
modelBuildingContext
);
entityUsage.name( "___Entity5___" );
final MutableMemberDetails idField = (MutableMemberDetails) jdkClassDetails.findFieldByName(
"id" );
idField.applyAnnotationUsage( JpaAnnotations.ID, modelBuildingContext );
return jdkClassDetails;
}
);
contributions.contributeManagedClass( entity5Details );
}
@ -326,17 +360,50 @@ public class AdditionalMappingContributorTests {
InFlightMetadataCollector metadata,
ResourceStreamLocator resourceStreamLocator,
MetadataBuildingContext buildingContext) {
final ClassDetailsRegistry classDetailsRegistry = buildingContext.getMetadataCollector()
.getSourceModelBuildingContext()
.getClassDetailsRegistry();
contributeEntity6Details( contributions, classDetailsRegistry );
final SourceModelBuildingContext sourceModelBuildingContext = buildingContext.getMetadataCollector()
.getSourceModelBuildingContext();
final ClassDetailsRegistry classDetailsRegistry = sourceModelBuildingContext.getClassDetailsRegistry();
contributeEntity6Details( contributions, sourceModelBuildingContext, classDetailsRegistry );
}
private void contributeEntity6Details(
AdditionalMappingContributions contributions,
SourceModelBuildingContext modelBuildingContext,
ClassDetailsRegistry classDetailsRegistry) {
final ClassDetails entity6Details = classDetailsRegistry.resolveClassDetails(
"Entity6"
final ClassDetails entity6Details = ModelsHelper.resolveClassDetails(
"Entity6",
classDetailsRegistry,
() -> {
final DynamicClassDetails classDetails = new DynamicClassDetails(
"Entity6",
modelBuildingContext
);
final EntityJpaAnnotation entityUsage = (EntityJpaAnnotation) classDetails.applyAnnotationUsage(
JpaAnnotations.ENTITY,
modelBuildingContext
);
entityUsage.name( "Entity6" );
final DynamicFieldDetails idMember = classDetails.applyAttribute(
"id",
classDetailsRegistry.resolveClassDetails( Integer.class.getName() ),
false,
false,
modelBuildingContext
);
idMember.applyAnnotationUsage( JpaAnnotations.ID, modelBuildingContext );
final DynamicFieldDetails nameMember = classDetails.applyAttribute(
"name",
classDetailsRegistry.resolveClassDetails( String.class.getName() ),
false,
false,
modelBuildingContext
);
nameMember.applyAnnotationUsage( HibernateAnnotations.NATIONALIZED, modelBuildingContext );
return classDetails;
}
);
contributions.contributeManagedClass( entity6Details );
}