HHH-18103 Correct metamodel for embeddables with a mapped superclass

This commit is contained in:
Marco Belladelli 2024-05-23 11:46:59 +02:00
parent 00c7707de0
commit 062afdb6cd
9 changed files with 169 additions and 64 deletions

View File

@ -287,7 +287,7 @@ public class ClassPropertyHolder extends AbstractPropertyHolder {
} }
if ( inheritanceState.isEmbeddableSuperclass() ) { if ( inheritanceState.isEmbeddableSuperclass() ) {
persistentClass.addMappedSuperclassProperty( property ); persistentClass.addMappedSuperclassProperty( property );
addPropertyToMappedSuperclass( property, declaringClass ); addPropertyToMappedSuperclass( property, declaringClass, getContext() );
} }
else { else {
persistentClass.addProperty( property ); persistentClass.addProperty( property );
@ -298,10 +298,10 @@ public class ClassPropertyHolder extends AbstractPropertyHolder {
} }
} }
private void addPropertyToMappedSuperclass(Property prop, XClass declaringClass) { static void addPropertyToMappedSuperclass(Property prop, XClass declaringClass, MetadataBuildingContext context) {
final Class<?> type = getContext().getBootstrapContext().getReflectionManager().toClass( declaringClass ); final Class<?> type = context.getBootstrapContext().getReflectionManager().toClass( declaringClass );
final MappedSuperclass superclass = getContext().getMetadataCollector().getMappedSuperclass( type ); final MappedSuperclass superclass = context.getMetadataCollector().getMappedSuperclass( type );
prepareActualProperty( prop, type, true, getContext(), superclass::addDeclaredProperty ); prepareActualProperty( prop, type, true, context, superclass::addDeclaredProperty );
} }
static void prepareActualProperty( static void prepareActualProperty(
@ -458,7 +458,7 @@ public class ClassPropertyHolder extends AbstractPropertyHolder {
} }
if ( inheritanceState.isEmbeddableSuperclass() ) { if ( inheritanceState.isEmbeddableSuperclass() ) {
join.addMappedSuperclassProperty( property ); join.addMappedSuperclassProperty( property );
addPropertyToMappedSuperclass( property, declaringClass ); addPropertyToMappedSuperclass( property, declaringClass, getContext() );
} }
else { else {
join.addProperty( property ); join.addProperty( property );

View File

@ -30,7 +30,10 @@ import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable; import jakarta.persistence.JoinTable;
import static org.hibernate.boot.model.internal.ClassPropertyHolder.addPropertyToMappedSuperclass;
import static org.hibernate.boot.model.internal.ClassPropertyHolder.handleGenericComponentProperty;
import static org.hibernate.boot.model.internal.HCANNHelper.hasAnnotation; import static org.hibernate.boot.model.internal.HCANNHelper.hasAnnotation;
import static org.hibernate.internal.util.NullnessUtil.castNonNull;
import static org.hibernate.internal.util.StringHelper.isEmpty; import static org.hibernate.internal.util.StringHelper.isEmpty;
import static org.hibernate.internal.util.StringHelper.qualifyConditionally; import static org.hibernate.internal.util.StringHelper.qualifyConditionally;
import static org.hibernate.spi.NavigablePath.IDENTIFIER_MAPPER_PROPERTY; import static org.hibernate.spi.NavigablePath.IDENTIFIER_MAPPER_PROPERTY;
@ -67,6 +70,7 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
private final Component component; private final Component component;
private final boolean isOrWithinEmbeddedId; private final boolean isOrWithinEmbeddedId;
private final boolean isWithinElementCollection; private final boolean isWithinElementCollection;
private final Map<XClass, InheritanceState> inheritanceStatePerClass;
private final String embeddedAttributeName; private final String embeddedAttributeName;
private final Map<String,AttributeConversionInfo> attributeConversionInfoMap; private final Map<String,AttributeConversionInfo> attributeConversionInfoMap;
@ -76,7 +80,8 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
String path, String path,
PropertyData inferredData, PropertyData inferredData,
PropertyHolder parent, PropertyHolder parent,
MetadataBuildingContext context) { MetadataBuildingContext context,
Map<XClass, InheritanceState> inheritanceStatePerClass) {
super( path, parent, inferredData.getPropertyClass(), context ); super( path, parent, inferredData.getPropertyClass(), context );
final XProperty embeddedXProperty = inferredData.getProperty(); final XProperty embeddedXProperty = inferredData.getProperty();
setCurrentProperty( embeddedXProperty ); setCurrentProperty( embeddedXProperty );
@ -85,6 +90,7 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
|| hasAnnotation( embeddedXProperty, Id.class, EmbeddedId.class ); || hasAnnotation( embeddedXProperty, Id.class, EmbeddedId.class );
this.isWithinElementCollection = parent.isWithinElementCollection() || this.isWithinElementCollection = parent.isWithinElementCollection() ||
parent instanceof CollectionPropertyHolder; parent instanceof CollectionPropertyHolder;
this.inheritanceStatePerClass = inheritanceStatePerClass;
if ( embeddedXProperty != null ) { if ( embeddedXProperty != null ) {
this.embeddedAttributeName = embeddedXProperty.getName(); this.embeddedAttributeName = embeddedXProperty.getName();
@ -314,6 +320,13 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
@Override @Override
public void addProperty(Property prop, XClass declaringClass) { public void addProperty(Property prop, XClass declaringClass) {
handleGenericComponentProperty( prop, getContext() );
if ( declaringClass != null ) {
final InheritanceState inheritanceState = inheritanceStatePerClass.get( declaringClass );
if ( inheritanceState != null && inheritanceState.isEmbeddableSuperclass() ) {
addPropertyToMappedSuperclass( prop, declaringClass, getContext() );
}
}
component.addProperty( prop, declaringClass ); component.addProperty( prop, declaringClass );
} }

View File

@ -353,7 +353,8 @@ public class EmbeddableBinder {
subpath, subpath,
inferredData, inferredData,
propertyHolder, propertyHolder,
context context,
inheritanceStatePerClass
); );
// propertyHolder here is the owner of the component property. // propertyHolder here is the owner of the component property.
@ -381,18 +382,23 @@ public class EmbeddableBinder {
context context
); );
bindDiscriminator( final InheritanceState inheritanceState = inheritanceStatePerClass.get( returnedClassOrElement );
component, if ( inheritanceState != null ) {
returnedClassOrElement, inheritanceState.postProcess( component );
propertyHolder, // Main entry point for binding embeddable inheritance
subholder, bindDiscriminator(
inferredData, component,
inheritanceStatePerClass, returnedClassOrElement,
context propertyHolder,
); subholder,
inferredData,
inheritanceState,
context
);
}
final Map<String, String> subclassToSuperclass = component.isPolymorphic() ? new HashMap<>() : null;
final XClass annotatedClass = inferredData.getPropertyClass(); final XClass annotatedClass = inferredData.getPropertyClass();
final Map<String, String> subclassToSuperclass = component.isPolymorphic() ? new HashMap<>() : null;
final List<PropertyData> classElements = collectClassElements( final List<PropertyData> classElements = collectClassElements(
propertyAccessor, propertyAccessor,
context, context,
@ -487,13 +493,11 @@ public class EmbeddableBinder {
PropertyHolder parentHolder, PropertyHolder parentHolder,
PropertyHolder holder, PropertyHolder holder,
PropertyData propertyData, PropertyData propertyData,
Map<XClass, InheritanceState> inheritanceStatePerClass, InheritanceState inheritanceState,
MetadataBuildingContext context) { MetadataBuildingContext context) {
final InheritanceState inheritanceState = inheritanceStatePerClass.get( componentClass );
if ( inheritanceState == null ) { if ( inheritanceState == null ) {
return; return;
} }
final AnnotatedDiscriminatorColumn discriminatorColumn = processEmbeddableDiscriminatorProperties( final AnnotatedDiscriminatorColumn discriminatorColumn = processEmbeddableDiscriminatorProperties(
componentClass, componentClass,
propertyData, propertyData,

View File

@ -17,7 +17,9 @@ import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.boot.spi.AccessType; import org.hibernate.boot.spi.AccessType;
import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.PropertyData; import org.hibernate.boot.spi.PropertyData;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Table;
import jakarta.persistence.Access; import jakarta.persistence.Access;
import jakarta.persistence.EmbeddedId; import jakarta.persistence.EmbeddedId;
@ -163,6 +165,15 @@ public class InheritanceState {
return elementsToProcess; return elementsToProcess;
} }
public void postProcess(Component component) {
if ( classesToProcessForMappedSuperclass.isEmpty() ) {
// Component classes might be processed more than once,
// so only do this the first time we encounter them
getMappedSuperclassesTillNextEntityOrdered();
}
addMappedSuperClassInMetadata( component );
}
public XClass getClassWithIdClass(boolean evenIfSubclass) { public XClass getClassWithIdClass(boolean evenIfSubclass) {
if ( !evenIfSubclass && hasParents() ) { if ( !evenIfSubclass && hasParents() ) {
return null; return null;
@ -300,7 +311,21 @@ public class InheritanceState {
while ( superclassState != null && superclassState.isEmbeddableSuperclass() ); while ( superclassState != null && superclassState.isEmbeddableSuperclass() );
} }
private void addMappedSuperClassInMetadata(Component component) {
org.hibernate.mapping.MappedSuperclass mappedSuperclass = processMappedSuperclass( component.getTable() );
if ( mappedSuperclass != null ) {
component.setMappedSuperclass( mappedSuperclass );
}
}
private void addMappedSuperClassInMetadata(PersistentClass persistentClass) { private void addMappedSuperClassInMetadata(PersistentClass persistentClass) {
org.hibernate.mapping.MappedSuperclass mappedSuperclass = processMappedSuperclass( persistentClass.getImplicitTable() );
if ( mappedSuperclass != null ) {
persistentClass.setSuperMappedSuperclass( mappedSuperclass );
}
}
private org.hibernate.mapping.MappedSuperclass processMappedSuperclass(Table implicitTable) {
//add @MappedSuperclass in the metadata //add @MappedSuperclass in the metadata
// classes from 0 to n-1 are @MappedSuperclass and should be linked // classes from 0 to n-1 are @MappedSuperclass and should be linked
final InheritanceState superEntityState = getInheritanceStateOfSuperEntity( clazz, inheritanceStatePerClass ); final InheritanceState superEntityState = getInheritanceStateOfSuperEntity( clazz, inheritanceStatePerClass );
@ -317,14 +342,12 @@ 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, persistentClass.getImplicitTable() ); mappedSuperclass = new org.hibernate.mapping.MappedSuperclass( parentSuperclass, superEntity, implicitTable );
mappedSuperclass.setMappedClass( type ); mappedSuperclass.setMappedClass( type );
buildingContext.getMetadataCollector().addMappedSuperclass( type, mappedSuperclass ); buildingContext.getMetadataCollector().addMappedSuperclass( type, mappedSuperclass );
} }
} }
if ( mappedSuperclass != null ) { return mappedSuperclass;
persistentClass.setSuperMappedSuperclass( mappedSuperclass );
}
} }
public static final class ElementsToProcess { public static final class ElementsToProcess {

View File

@ -54,8 +54,9 @@ public final class PropertyHolderBuilder {
String path, String path,
PropertyData inferredData, PropertyData inferredData,
PropertyHolder parent, PropertyHolder parent,
MetadataBuildingContext context) { MetadataBuildingContext context,
return new ComponentPropertyHolder( component, path, inferredData, parent, context ); Map<XClass, InheritanceState> inheritanceStatePerClass) {
return new ComponentPropertyHolder( component, path, inferredData, parent, context, inheritanceStatePerClass );
} }
/** /**

View File

@ -86,6 +86,7 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
private boolean isKey; private boolean isKey;
private Boolean isGeneric; private Boolean isGeneric;
private String roleName; private String roleName;
private MappedSuperclass mappedSuperclass;
private Value discriminator; private Value discriminator;
private transient DiscriminatorType<?> discriminatorType; private transient DiscriminatorType<?> discriminatorType;
private Map<Object, String> discriminatorValues; private Map<Object, String> discriminatorValues;
@ -601,6 +602,14 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
this.roleName = roleName; this.roleName = roleName;
} }
public MappedSuperclass getMappedSuperclass() {
return mappedSuperclass;
}
public void setMappedSuperclass(MappedSuperclass mappedSuperclass) {
this.mappedSuperclass = mappedSuperclass;
}
public Value getDiscriminator() { public Value getDiscriminator() {
return discriminator; return discriminator;
} }

View File

@ -24,6 +24,7 @@ import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Component; import org.hibernate.mapping.Component;
import org.hibernate.mapping.List; import org.hibernate.mapping.List;
import org.hibernate.mapping.Map; import org.hibernate.mapping.Map;
import org.hibernate.mapping.MappedSuperclass;
import org.hibernate.mapping.OneToMany; import org.hibernate.mapping.OneToMany;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property; import org.hibernate.mapping.Property;
@ -44,6 +45,7 @@ import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
import org.hibernate.metamodel.model.domain.IdentifiableDomainType; import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
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.PersistentAttribute; import org.hibernate.metamodel.model.domain.PersistentAttribute;
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;
@ -263,10 +265,20 @@ public class AttributeFactory {
} }
} }
final MappedSuperclass mappedSuperclass = component.getMappedSuperclass();
final MappedSuperclassDomainType<? super Y> superType;
if ( mappedSuperclass != null ) {
//noinspection unchecked
superType = (MappedSuperclassDomainType<? super Y>) context.locateMappedSuperclassType( mappedSuperclass );
}
else {
superType = null;
}
final DomainType<?> discriminatorType = component.isPolymorphic() ? component.getDiscriminatorType() : null; final DomainType<?> discriminatorType = component.isPolymorphic() ? component.getDiscriminatorType() : null;
final EmbeddableTypeImpl<Y> embeddableType = new EmbeddableTypeImpl<>( final EmbeddableTypeImpl<Y> embeddableType = new EmbeddableTypeImpl<>(
context.getJavaTypeRegistry().resolveManagedTypeDescriptor( embeddableClass ), context.getJavaTypeRegistry().resolveManagedTypeDescriptor( embeddableClass ),
null, superType,
discriminatorType, discriminatorType,
false, false,
context.getJpaMetamodel() context.getJpaMetamodel()
@ -409,7 +421,7 @@ public class AttributeFactory {
else if ( persistenceType == Type.PersistenceType.MAPPED_SUPERCLASS ) { else if ( persistenceType == Type.PersistenceType.MAPPED_SUPERCLASS ) {
final PersistentClass persistentClass = final PersistentClass persistentClass =
metadataContext.getPersistentClassHostingProperties( (MappedSuperclassTypeImpl<?>) ownerType ); metadataContext.getPersistentClassHostingProperties( (MappedSuperclassTypeImpl<?>) ownerType );
return metadataContext.getMetamodel().findEntityDescriptor( persistentClass.getClassName() ); return persistentClass != null ? metadataContext.getMetamodel().findEntityDescriptor( persistentClass.getClassName() ) : null;
} }
else { else {
throw new AssertionFailure( "Cannot get the metamodel for PersistenceType: " + persistenceType ); throw new AssertionFailure( "Cannot get the metamodel for PersistenceType: " + persistenceType );
@ -646,6 +658,13 @@ public class AttributeFactory {
private static final MemberResolver embeddedMemberResolver = (attributeContext, metadataContext) -> { private static final MemberResolver embeddedMemberResolver = (attributeContext, metadataContext) -> {
// the owner is an embeddable // the owner is an embeddable
final EmbeddableDomainType<?> ownerType = (EmbeddableDomainType<?>) attributeContext.getOwnerType(); final EmbeddableDomainType<?> ownerType = (EmbeddableDomainType<?>) attributeContext.getOwnerType();
return resolveEmbeddedMember( attributeContext.getPropertyMapping(), ownerType, metadataContext );
};
private static Member resolveEmbeddedMember(
Property property,
EmbeddableDomainType<?> ownerType,
MetadataContext metadataContext) {
final Component ownerBootDescriptor = metadataContext.getEmbeddableBootDescriptor( ownerType ); final Component ownerBootDescriptor = metadataContext.getEmbeddableBootDescriptor( ownerType );
final CompositeTypeImplementor ownerComponentType = (CompositeTypeImplementor) ownerBootDescriptor.getType(); final CompositeTypeImplementor ownerComponentType = (CompositeTypeImplementor) ownerBootDescriptor.getType();
@ -655,16 +674,15 @@ public class AttributeFactory {
ownerRepresentationStrategy( metadataContext, ownerMappingModelDescriptor, ownerBootDescriptor ); ownerRepresentationStrategy( metadataContext, ownerMappingModelDescriptor, ownerBootDescriptor );
if ( ownerRepStrategy.getMode() == RepresentationMode.MAP ) { if ( ownerRepStrategy.getMode() == RepresentationMode.MAP ) {
final Property propertyMapping = attributeContext.getPropertyMapping(); return new MapMember( property.getName(), property.getType().getReturnedClass() );
return new MapMember( propertyMapping.getName(), propertyMapping.getType().getReturnedClass() );
} }
else { else {
return ownerRepStrategy return ownerRepStrategy
.resolvePropertyAccess( attributeContext.getPropertyMapping() ) .resolvePropertyAccess( property )
.getGetter() .getGetter()
.getMember(); .getMember();
} }
}; }
private static EmbeddableRepresentationStrategy ownerRepresentationStrategy( private static EmbeddableRepresentationStrategy ownerRepresentationStrategy(
MetadataContext metadataContext, EmbeddableValuedModelPart ownerMappingModelDescriptor, Component ownerBootDescriptor) { MetadataContext metadataContext, EmbeddableValuedModelPart ownerMappingModelDescriptor, Component ownerBootDescriptor) {
@ -688,7 +706,11 @@ public class AttributeFactory {
private static final MemberResolver virtualIdentifierMemberResolver = (attributeContext, metadataContext) -> { private static final MemberResolver virtualIdentifierMemberResolver = (attributeContext, metadataContext) -> {
final AbstractIdentifiableType<?> identifiableType = (AbstractIdentifiableType<?>) attributeContext.getOwnerType(); final AbstractIdentifiableType<?> identifiableType = (AbstractIdentifiableType<?>) attributeContext.getOwnerType();
final EntityPersister entityPersister = getDeclarerEntityPersister( identifiableType, metadataContext ); final EntityPersister declaringEntity = getDeclaringEntity( identifiableType, metadataContext );
return resolveVirtualIdentifierMember( attributeContext.getPropertyMapping(), declaringEntity );
};
private static Member resolveVirtualIdentifierMember( Property property, EntityPersister entityPersister) {
final EntityIdentifierMapping identifierMapping = entityPersister.getIdentifierMapping(); final EntityIdentifierMapping identifierMapping = entityPersister.getIdentifierMapping();
if ( identifierMapping.getNature() != EntityIdentifierMapping.Nature.VIRTUAL ) { if ( identifierMapping.getNature() != EntityIdentifierMapping.Nature.VIRTUAL ) {
@ -697,7 +719,7 @@ public class AttributeFactory {
final CompositeIdentifierMapping cid = (CompositeIdentifierMapping) identifierMapping; final CompositeIdentifierMapping cid = (CompositeIdentifierMapping) identifierMapping;
final EmbeddableMappingType embeddable = cid.getPartMappingType(); final EmbeddableMappingType embeddable = cid.getPartMappingType();
final String attributeName = attributeContext.getPropertyMapping().getName(); final String attributeName = property.getName();
final AttributeMapping attributeMapping = embeddable.findAttributeMapping( attributeName ); final AttributeMapping attributeMapping = embeddable.findAttributeMapping( attributeName );
if ( attributeMapping == null ) { if ( attributeMapping == null ) {
throw new PropertyNotFoundException( throw new PropertyNotFoundException(
@ -708,9 +730,9 @@ public class AttributeFactory {
final Getter getter = attributeMapping.getPropertyAccess().getGetter(); final Getter getter = attributeMapping.getPropertyAccess().getGetter();
return getter instanceof PropertyAccessMapImpl.GetterImpl return getter instanceof PropertyAccessMapImpl.GetterImpl
? new MapMember( attributeName, attributeContext.getPropertyMapping().getType().getReturnedClass() ) ? new MapMember( attributeName, property.getType().getReturnedClass() )
: getter.getMember(); : getter.getMember();
}; }
/** /**
* A {@link Member} resolver for normal attributes. * A {@link Member} resolver for normal attributes.
@ -722,29 +744,66 @@ public class AttributeFactory {
if ( Type.PersistenceType.EMBEDDABLE == persistenceType ) { if ( Type.PersistenceType.EMBEDDABLE == persistenceType ) {
return embeddedMemberResolver.resolveMember( attributeContext, metadataContext ); return embeddedMemberResolver.resolveMember( attributeContext, metadataContext );
} }
else if ( Type.PersistenceType.ENTITY == persistenceType else if ( Type.PersistenceType.MAPPED_SUPERCLASS == persistenceType ) {
|| Type.PersistenceType.MAPPED_SUPERCLASS == persistenceType ) { return resolveMappedSuperclassMember(
final AbstractIdentifiableType<?> identifiableType = (AbstractIdentifiableType<?>) ownerType; property,
final EntityPersister declaringEntityPersister = getDeclaringEntity( identifiableType, metadataContext ); (MappedSuperclassDomainType<?>) ownerType,
final String propertyName = property.getName(); metadataContext
);
final AttributeMapping attributeMapping = declaringEntityPersister.findAttributeMapping( propertyName ); }
if ( attributeMapping == null ) { else if ( Type.PersistenceType.ENTITY == persistenceType ) {
// just like in #determineIdentifierJavaMember , this *should* indicate we have an IdClass mapping return resolveEntityMember( property, getDeclaringEntity( (AbstractIdentifiableType<?>) ownerType, metadataContext ) );
return virtualIdentifierMemberResolver.resolveMember( attributeContext, metadataContext );
}
else {
final Getter getter = getter( declaringEntityPersister, property );
return getter instanceof PropertyAccessMapImpl.GetterImpl
? new MapMember( propertyName, property.getType().getReturnedClass() )
: getter.getMember();
}
} }
else { else {
throw new IllegalArgumentException( "Unexpected owner type : " + persistenceType ); throw new IllegalArgumentException( "Unexpected owner type : " + persistenceType );
} }
}; };
private static Member resolveEntityMember(Property property, EntityPersister declaringEntity) {
final String propertyName = property.getName();
final AttributeMapping attributeMapping = declaringEntity.findAttributeMapping( propertyName );
if ( attributeMapping == null ) {
// just like in #determineIdentifierJavaMember , this *should* indicate we have an IdClass mapping
return resolveVirtualIdentifierMember( property, declaringEntity );
}
else {
final Getter getter = getter( declaringEntity, property );
return getter instanceof PropertyAccessMapImpl.GetterImpl
? new MapMember( propertyName, property.getType().getReturnedClass() )
: getter.getMember();
}
}
private static Member resolveMappedSuperclassMember(
Property property,
MappedSuperclassDomainType<?> ownerType,
MetadataContext metadataContext) {
final EntityPersister declaringEntity = getDeclaringEntity( (AbstractIdentifiableType<?>) ownerType, metadataContext );
if ( declaringEntity != null ) {
return resolveEntityMember( property, declaringEntity );
}
else {
final ManagedDomainType<?> subType = ownerType.getSubTypes().iterator().next();
final Type.PersistenceType persistenceType = subType.getPersistenceType();
if ( persistenceType == Type.PersistenceType.ENTITY ) {
return resolveEntityMember( property, getDeclaringEntity( (AbstractIdentifiableType<?>) subType, metadataContext ) );
}
else if ( persistenceType == Type.PersistenceType.EMBEDDABLE ) {
return resolveEmbeddedMember( property, (EmbeddableDomainType<?>) subType, metadataContext );
}
else if ( persistenceType == Type.PersistenceType.MAPPED_SUPERCLASS ) {
return resolveMappedSuperclassMember(
property,
(MappedSuperclassDomainType<?>) subType,
metadataContext
);
}
else {
throw new IllegalArgumentException( "Unexpected sub-type: " + persistenceType );
}
}
}
private final MemberResolver identifierMemberResolver = (attributeContext, metadataContext) -> { private final MemberResolver identifierMemberResolver = (attributeContext, metadataContext) -> {
final AbstractIdentifiableType<?> identifiableType = final AbstractIdentifiableType<?> identifiableType =
(AbstractIdentifiableType<?>) attributeContext.getOwnerType(); (AbstractIdentifiableType<?>) attributeContext.getOwnerType();

View File

@ -211,7 +211,9 @@ public class MetadataContext {
identifiableTypesByName.put( mappedSuperclassType.getTypeName(), mappedSuperclassType ); identifiableTypesByName.put( mappedSuperclassType.getTypeName(), mappedSuperclassType );
mappedSuperclassByMappedSuperclassMapping.put( mappedSuperclass, mappedSuperclassType ); mappedSuperclassByMappedSuperclassMapping.put( mappedSuperclass, mappedSuperclassType );
orderedMappings.add( mappedSuperclass ); orderedMappings.add( mappedSuperclass );
mappedSuperClassTypeToPersistentClass.put( mappedSuperclassType, getEntityWorkedOn() ); if ( !stackOfPersistentClassesBeingProcessed.isEmpty() ) {
mappedSuperClassTypeToPersistentClass.put( mappedSuperclassType, getEntityWorkedOn() );
}
knownMappedSuperclasses.remove( mappedSuperclass ); knownMappedSuperclasses.remove( mappedSuperclass );
} }
@ -804,14 +806,7 @@ public class MetadataContext {
} }
public PersistentClass getPersistentClassHostingProperties(MappedSuperclassTypeImpl<?> mappedSuperclassType) { public PersistentClass getPersistentClassHostingProperties(MappedSuperclassTypeImpl<?> mappedSuperclassType) {
final PersistentClass persistentClass = mappedSuperClassTypeToPersistentClass.get( mappedSuperclassType ); return mappedSuperClassTypeToPersistentClass.get( mappedSuperclassType );
if ( persistentClass == null ) {
throw new AssertionFailure(
"Could not find PersistentClass for MappedSuperclassType: "
+ mappedSuperclassType.getJavaType()
);
}
return persistentClass;
} }
public Set<MappedSuperclass> getUnusedMappedSuperclasses() { public Set<MappedSuperclass> getUnusedMappedSuperclasses() {

View File

@ -32,7 +32,8 @@ public class AuditedEmbeddableWithNoDeclaredDataTest extends BaseEnversJPAFuncti
return new Class[] { return new Class[] {
EntityWithAuditedEmbeddableWithNoDeclaredData.class, EntityWithAuditedEmbeddableWithNoDeclaredData.class,
AbstractAuditedEmbeddable.class, AbstractAuditedEmbeddable.class,
AuditedEmbeddableWithDeclaredData.class AuditedEmbeddableWithDeclaredData.class,
AuditedEmbeddableWithNoDeclaredData.class,
}; };
} }