From a24081a096106619237743ba2af764fd9d8337f4 Mon Sep 17 00:00:00 2001 From: Marco Belladelli Date: Mon, 27 Mar 2023 15:54:14 +0200 Subject: [PATCH] HHH-16378 Handle non-embeddable generic attribute paths --- .../metamodel/internal/AttributeFactory.java | 21 ++++++- .../metamodel/internal/MetadataContext.java | 60 ++++++------------- .../domain/AbstractIdentifiableType.java | 3 +- .../model/domain/AbstractManagedType.java | 22 +++---- .../model/domain/ManagedDomainType.java | 4 +- .../internal/AbstractPluralAttribute.java | 10 +++- .../internal/AnyMappingSqmPathSource.java | 3 +- .../domain/internal/AttributeContainer.java | 2 +- .../domain/internal/BasicSqmPathSource.java | 10 +++- .../domain/internal/EntitySqmPathSource.java | 11 +++- .../domain/internal/ListAttributeImpl.java | 7 ++- .../domain/internal/MapAttributeImpl.java | 7 ++- .../internal/PluralAttributeBuilder.java | 9 +++ .../org/hibernate/query/criteria/JpaPath.java | 3 +- .../sqm/internal/SqmMappingModelHelper.java | 17 ++++-- .../sqm/tree/domain/AbstractSqmPath.java | 17 +++++- .../query/sqm/tree/domain/SqmCteRoot.java | 5 ++ .../query/sqm/tree/domain/SqmDerivedRoot.java | 5 ++ .../domain/SqmEmbeddedValuedSimplePath.java | 28 +-------- .../domain/SqmPolymorphicRootDescriptor.java | 4 +- 20 files changed, 141 insertions(+), 107 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java index bbe7fe3dbb..34af619405 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java @@ -23,6 +23,7 @@ import org.hibernate.mapping.Map; import org.hibernate.mapping.OneToMany; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; +import org.hibernate.mapping.SimpleValue; import org.hibernate.mapping.Value; import org.hibernate.metamodel.AttributeClassification; import org.hibernate.metamodel.RepresentationMode; @@ -36,6 +37,7 @@ import org.hibernate.metamodel.mapping.EntityVersionMapping; import org.hibernate.metamodel.model.domain.AbstractIdentifiableType; import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.EmbeddableDomainType; +import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.IdentifiableDomainType; import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.PersistentAttribute; @@ -116,7 +118,11 @@ public class AttributeFactory { if ( attributeMetadata instanceof PluralAttributeMetadata ) { //noinspection rawtypes - return PluralAttributeBuilder.build( (PluralAttributeMetadata) attributeMetadata, metadataContext ); + return PluralAttributeBuilder.build( + (PluralAttributeMetadata) attributeMetadata, + property.isGeneric(), + metadataContext + ); } final SingularAttributeMetadata singularAttributeMetadata = (SingularAttributeMetadata) attributeMetadata; @@ -221,7 +227,18 @@ public class AttributeFactory { public static DomainType determineSimpleType(ValueContext typeContext, MetadataContext context) { switch ( typeContext.getValueClassification() ) { case BASIC: { - return context.resolveBasicType( typeContext.getJpaBindableType() ); + Class returnedClass = typeContext.getJpaBindableType(); + if ( returnedClass.isAssignableFrom( Object.class ) ) { + final SimpleValue simpleValue = (SimpleValue) typeContext.getHibernateValue(); + if ( simpleValue.getTypeParameters() != null && typeContext.getAttributeMetadata() + .getOwnerType() instanceof EntityDomainType ) { + // Due to how generics work with Java, the type of generic fields will always + // be reported as Object. We need to resolve type based on the actual property + // value for basic attributes in entities which specify concrete type parameters. + returnedClass = simpleValue.getType().getReturnedClass(); + } + } + return context.resolveBasicType( returnedClass ); } case ENTITY: { final org.hibernate.type.Type type = typeContext.getHibernateValue().getType(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java index 20c2f74c63..e0fa61f210 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java @@ -273,7 +273,7 @@ public class MetadataContext { applyIdMetadata( safeMapping, jpaMapping ); applyVersionAttribute( safeMapping, jpaMapping ); - applyGenericEmbeddableProperties( safeMapping, jpaMapping ); + applyGenericProperties( safeMapping, jpaMapping ); for ( Property property : safeMapping.getDeclaredProperties() ) { if ( property.getValue() == safeMapping.getIdentifierMapper() ) { @@ -430,16 +430,15 @@ public class MetadataContext { //noinspection unchecked attributeContainer.getInFlightAccess().applyIdAttribute( idAttribute ); } - else if ( persistentClass.getIdentifier() instanceof Component - && persistentClass.getIdentifierProperty() != getSuperclassIdentifier( persistentClass ) ) { - // If the identifier is a generic component, we have to call buildIdAttribute anyway, - // as this will create and register the EmbeddableType for the subtype - final SingularPersistentAttribute concreteEmbeddable = attributeFactory.buildIdAttribute( + final Property superclassIdentifier = getMappedSuperclassIdentifier( persistentClass ); + if ( superclassIdentifier != null && superclassIdentifier.isGeneric() ) { + // If the superclass identifier is generic we have to build the attribute to register the concrete type + final SingularPersistentAttribute concreteIdentifier = attributeFactory.buildIdAttribute( identifiableType, persistentClass.getIdentifierProperty() ); //noinspection unchecked - attributeContainer.getInFlightAccess().addConcreteEmbeddableAttribute( concreteEmbeddable ); + attributeContainer.getInFlightAccess().addConcreteGenericAttribute( concreteIdentifier ); } } else { @@ -489,30 +488,14 @@ public class MetadataContext { } } - private Property getSuperclassIdentifier(PersistentClass persistentClass) { - final Property declaredIdentifierProperty = persistentClass.getDeclaredIdentifierProperty(); - if ( declaredIdentifierProperty != null ) { - return declaredIdentifierProperty; - } - if ( persistentClass.getSuperMappedSuperclass() != null ) { - return getSuperclassIdentifier( persistentClass.getSuperMappedSuperclass() ); - } - else if ( persistentClass.getSuperclass() != null ) { - return getSuperclassIdentifier( persistentClass.getSuperclass() ); - } - return null; - } - - private Property getSuperclassIdentifier(MappedSuperclass persistentClass) { - final Property declaredIdentifierProperty = persistentClass.getDeclaredIdentifierProperty(); - if ( declaredIdentifierProperty != null ) { - return declaredIdentifierProperty; - } - if ( persistentClass.getSuperMappedSuperclass() != null ) { - return getSuperclassIdentifier( persistentClass.getSuperMappedSuperclass() ); - } - else if ( persistentClass.getSuperPersistentClass() != null ) { - return getSuperclassIdentifier( persistentClass.getSuperPersistentClass() ); + private Property getMappedSuperclassIdentifier(PersistentClass persistentClass) { + MappedSuperclass mappedSuperclass = getMappedSuperclass( persistentClass ); + while ( mappedSuperclass != null ) { + final Property declaredIdentifierProperty = mappedSuperclass.getDeclaredIdentifierProperty(); + if ( declaredIdentifierProperty != null ) { + return declaredIdentifierProperty; + } + mappedSuperclass = getMappedSuperclass( mappedSuperclass ); } return null; } @@ -573,20 +556,15 @@ public class MetadataContext { } } - private void applyGenericEmbeddableProperties( - PersistentClass persistentClass, - EntityDomainType entityType) { + private void applyGenericProperties(PersistentClass persistentClass, EntityDomainType entityType) { MappedSuperclass mappedSuperclass = getMappedSuperclass( persistentClass ); while ( mappedSuperclass != null ) { for ( Property superclassProperty : mappedSuperclass.getDeclaredProperties() ) { - if ( superclassProperty.isGeneric() && superclassProperty.isComposite() ) { + if ( superclassProperty.isGeneric() ) { final Property property = persistentClass.getProperty( superclassProperty.getName() ); - final SingularPersistentAttribute attribute = (SingularPersistentAttribute) attributeFactory.buildAttribute( - entityType, - property - ); - //noinspection unchecked rawtypes - ( (AttributeContainer) entityType ).getInFlightAccess().addConcreteEmbeddableAttribute( attribute ); + final PersistentAttribute attribute = attributeFactory.buildAttribute( entityType, property ); + //noinspection unchecked + ( (AttributeContainer) entityType ).getInFlightAccess().addConcreteGenericAttribute( attribute ); } } mappedSuperclass = getMappedSuperclass( mappedSuperclass ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractIdentifiableType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractIdentifiableType.java index 1a9ab3275c..1f68776d1c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractIdentifiableType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractIdentifiableType.java @@ -416,7 +416,8 @@ public abstract class AbstractIdentifiableType EntityIdentifierMapping.ROLE_LOCAL_NAME, (SqmPathSource) id, (BasicDomainType) type, - Bindable.BindableType.SINGULAR_ATTRIBUTE + Bindable.BindableType.SINGULAR_ATTRIBUTE, + id.isGeneric() ); } else { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractManagedType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractManagedType.java index 6580d04c28..7486a5a0a0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractManagedType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractManagedType.java @@ -56,7 +56,7 @@ public abstract class AbstractManagedType private final Map> declaredSingularAttributes = new LinkedHashMap<>(); private volatile Map> declaredPluralAttributes ; - private volatile Map> declaredConcreteEmbeddedAttributes; + private volatile Map> declaredConcreteGenericAttributes; private final List subTypes = new ArrayList<>(); @@ -466,20 +466,20 @@ public abstract class AbstractManagedType // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Generic Embeddable attributes + // Generic attributes @Override - public SingularPersistentAttribute findConcreteEmbeddableAttribute(String name) { - SingularPersistentAttribute attribute = findDeclaredConcreteEmbeddableAttribute( name ); + public PersistentAttribute findConcreteGenericAttribute(String name) { + PersistentAttribute attribute = findDeclaredConcreteGenericAttribute( name ); if ( attribute == null && getSuperType() != null ) { - attribute = getSuperType().findDeclaredConcreteEmbeddableAttribute( name ); + attribute = getSuperType().findDeclaredConcreteGenericAttribute( name ); } return attribute; } @Override - public SingularPersistentAttribute findDeclaredConcreteEmbeddableAttribute(String name) { - return declaredConcreteEmbeddedAttributes == null ? null : declaredConcreteEmbeddedAttributes.get( name ); + public PersistentAttribute findDeclaredConcreteGenericAttribute(String name) { + return declaredConcreteGenericAttributes == null ? null : declaredConcreteGenericAttributes.get( name ); } @@ -760,11 +760,11 @@ public abstract class AbstractManagedType } @Override - public void addConcreteEmbeddableAttribute(SingularPersistentAttribute attribute) { - if ( declaredConcreteEmbeddedAttributes == null ) { - declaredConcreteEmbeddedAttributes = new HashMap<>(); + public void addConcreteGenericAttribute(PersistentAttribute attribute) { + if ( declaredConcreteGenericAttributes == null ) { + declaredConcreteGenericAttributes = new HashMap<>(); } - declaredConcreteEmbeddedAttributes.put( attribute.getName(), attribute ); + declaredConcreteGenericAttributes.put( attribute.getName(), attribute ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/ManagedDomainType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/ManagedDomainType.java index ba8ff2740f..a1d437d9a8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/ManagedDomainType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/ManagedDomainType.java @@ -59,12 +59,12 @@ public interface ManagedDomainType extends SqmExpressible, DomainType, SingularPersistentAttribute findSingularAttribute(String name); PluralPersistentAttribute findPluralAttribute(String name); - SingularPersistentAttribute findConcreteEmbeddableAttribute(String name); + PersistentAttribute findConcreteGenericAttribute(String name); PersistentAttribute findDeclaredAttribute(String name); SingularPersistentAttribute findDeclaredSingularAttribute(String name); PluralPersistentAttribute findDeclaredPluralAttribute(String name); - SingularPersistentAttribute findDeclaredConcreteEmbeddableAttribute(String name); + PersistentAttribute findDeclaredConcreteGenericAttribute(String name); SubGraphImplementor makeSubGraph(); SubGraphImplementor makeSubGraph(Class subClassType); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractPluralAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractPluralAttribute.java index 7fbb5d5e8f..91baccdd19 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractPluralAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractPluralAttribute.java @@ -54,7 +54,8 @@ public abstract class AbstractPluralAttribute this.elementPathSource = SqmMappingModelHelper.resolveSqmPathSource( CollectionPart.Nature.ELEMENT.getName(), builder.getValueType(), - BindableType.PLURAL_ATTRIBUTE + BindableType.PLURAL_ATTRIBUTE, + builder.isGeneric() ); } @@ -83,7 +84,7 @@ public abstract class AbstractPluralAttribute @Override public SqmPathSource getIntermediatePathSource(SqmPathSource pathSource) { - return pathSource == elementPathSource ? null : elementPathSource; + return pathSource.getPathName().equals( elementPathSource.getPathName() ) ? null : elementPathSource; } @Override @@ -154,4 +155,9 @@ public abstract class AbstractPluralAttribute lhs.nodeBuilder() ); } + + @Override + public boolean isGeneric() { + return elementPathSource.isGeneric(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AnyMappingSqmPathSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AnyMappingSqmPathSource.java index fb2764035d..14b32fb645 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AnyMappingSqmPathSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AnyMappingSqmPathSource.java @@ -33,7 +33,8 @@ public class AnyMappingSqmPathSource extends AbstractSqmPathSource { "id", null, (BasicDomainType) domainType.getKeyType(), - SINGULAR_ATTRIBUTE + SINGULAR_ATTRIBUTE, + false ); discriminatorPathSource = new AnyDiscriminatorSqmPathSource<>( localPathName, diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AttributeContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AttributeContainer.java index 6a6fd807f2..b2dd4ae58d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AttributeContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AttributeContainer.java @@ -66,7 +66,7 @@ public interface AttributeContainer { ); } - default void addConcreteEmbeddableAttribute(SingularPersistentAttribute idAttribute) { + default void addConcreteGenericAttribute(PersistentAttribute idAttribute) { throw new UnsupportedMappingException( "AttributeContainer [" + getClass().getName() + "] does not generic embeddables" ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/BasicSqmPathSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/BasicSqmPathSource.java index a945abd1e2..765c3188ae 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/BasicSqmPathSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/BasicSqmPathSource.java @@ -19,13 +19,16 @@ import org.hibernate.query.sqm.tree.domain.SqmPath; public class BasicSqmPathSource extends AbstractSqmPathSource implements ReturnableType { + private final boolean isGeneric; public BasicSqmPathSource( String localPathName, SqmPathSource pathModel, BasicDomainType domainType, - BindableType jpaBindableType) { + BindableType jpaBindableType, + boolean isGeneric) { super( localPathName, pathModel, domainType, jpaBindableType ); + this.isGeneric = isGeneric; } @Override @@ -66,6 +69,11 @@ public class BasicSqmPathSource return getExpressibleJavaType().getJavaTypeClass(); } + @Override + public boolean isGeneric() { + return isGeneric; + } + @Override public String toString() { return "BasicSqmPathSource(" + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntitySqmPathSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntitySqmPathSource.java index 2f4408c9e5..cec3aaaa48 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntitySqmPathSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntitySqmPathSource.java @@ -21,12 +21,16 @@ import org.hibernate.query.sqm.tree.from.SqmFrom; * @author Steve Ebersole */ public class EntitySqmPathSource extends AbstractSqmPathSource implements SqmJoinable { + private final boolean isGeneric; + public EntitySqmPathSource( String localPathName, SqmPathSource pathModel, EntityDomainType domainType, - BindableType jpaBindableType) { + BindableType jpaBindableType, + boolean isGeneric) { super( localPathName, pathModel, domainType, jpaBindableType ); + this.isGeneric = isGeneric; } @Override @@ -41,6 +45,11 @@ public class EntitySqmPathSource extends AbstractSqmPathSource implements return sqmPathType.findSubPathSource( name ); } + @Override + public boolean isGeneric() { + return isGeneric; + } + @Override public SqmPath createSqmPath(SqmPath lhs, SqmPathSource intermediatePathSource) { final NavigablePath navigablePath; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/ListAttributeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/ListAttributeImpl.java index bab596ff93..4ef9a2bc75 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/ListAttributeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/ListAttributeImpl.java @@ -31,7 +31,8 @@ class ListAttributeImpl extends AbstractPluralAttribute, E> imp //noinspection unchecked this.indexPathSource = (SqmPathSource) SqmMappingModelHelper.resolveSqmKeyPathSource( builder.getListIndexOrMapKeyType(), - BindableType.PLURAL_ATTRIBUTE + BindableType.PLURAL_ATTRIBUTE, + false ); } @@ -61,7 +62,9 @@ class ListAttributeImpl extends AbstractPluralAttribute, E> imp @Override public SqmPathSource getIntermediatePathSource(SqmPathSource pathSource) { - return pathSource == getElementPathSource() || pathSource == indexPathSource ? null : getElementPathSource(); + final String pathName = pathSource.getPathName(); + return pathName.equals( getElementPathSource().getPathName() ) + || pathName.equals( indexPathSource.getPathName() ) ? null : getElementPathSource(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MapAttributeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MapAttributeImpl.java index cc5d5e88cd..ea7455c943 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MapAttributeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MapAttributeImpl.java @@ -31,7 +31,8 @@ class MapAttributeImpl extends AbstractPluralAttribute, V> this.keyPathSource = SqmMappingModelHelper.resolveSqmKeyPathSource( xceBuilder.getListIndexOrMapKeyType(), - BindableType.PLURAL_ATTRIBUTE + BindableType.PLURAL_ATTRIBUTE, + xceBuilder.isGeneric() ); } @@ -71,7 +72,9 @@ class MapAttributeImpl extends AbstractPluralAttribute, V> @Override public SqmPathSource getIntermediatePathSource(SqmPathSource pathSource) { - return pathSource == getElementPathSource() || pathSource == keyPathSource ? null : getElementPathSource(); + final String pathName = pathSource.getPathName(); + return pathName.equals( getElementPathSource().getPathName() ) + || pathName.equals( keyPathSource.getPathName() ) ? null : getElementPathSource(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/PluralAttributeBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/PluralAttributeBuilder.java index 23c883aea2..220bb1e739 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/PluralAttributeBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/PluralAttributeBuilder.java @@ -32,6 +32,7 @@ import static org.hibernate.metamodel.internal.AttributeFactory.determineSimpleT */ public class PluralAttributeBuilder { private final JavaType collectionJtd; + private boolean isGeneric; private final AttributeClassification attributeClassification; private final CollectionClassification collectionClassification; @@ -46,6 +47,7 @@ public class PluralAttributeBuilder { public PluralAttributeBuilder( JavaType collectionJtd, + boolean isGeneric, AttributeClassification attributeClassification, CollectionClassification collectionClassification, DomainType elementType, @@ -54,6 +56,7 @@ public class PluralAttributeBuilder { Property property, Member member) { this.collectionJtd = collectionJtd; + this.isGeneric = isGeneric; this.attributeClassification = attributeClassification; this.collectionClassification = collectionClassification; this.elementType = elementType; @@ -66,6 +69,7 @@ public class PluralAttributeBuilder { @SuppressWarnings({ "unchecked", "rawtypes" }) public static PersistentAttribute build( PluralAttributeMetadata attributeMetadata, + boolean isGeneric, MetadataContext metadataContext) { final JavaType attributeJtd = metadataContext.getTypeConfiguration() @@ -74,6 +78,7 @@ public class PluralAttributeBuilder { final PluralAttributeBuilder builder = new PluralAttributeBuilder( attributeJtd, + isGeneric, attributeMetadata.getAttributeClassification(), attributeMetadata.getCollectionClassification(), AttributeFactory.determineSimpleType( @@ -155,6 +160,10 @@ public class PluralAttributeBuilder { return collectionJtd; } + public boolean isGeneric() { + return isGeneric; + } + public DomainType getValueType() { return elementType; } diff --git a/hibernate-core/src/main/java/org/hibernate/query/criteria/JpaPath.java b/hibernate-core/src/main/java/org/hibernate/query/criteria/JpaPath.java index bba385ed20..6261d41180 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/criteria/JpaPath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/criteria/JpaPath.java @@ -45,8 +45,7 @@ public interface JpaPath extends JpaExpression, Path { JpaPath treatAs(EntityDomainType treatJavaType); /** - * Get this pat's actual resolved model, e.g. the - * concrete embeddable type for generic embeddables + * Get this path's actual resolved model, i.e. the concrete type for generic attributes. */ SqmPathSource getResolvedModel(); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmMappingModelHelper.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmMappingModelHelper.java index 518ab4fffe..cbab5f0f37 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmMappingModelHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmMappingModelHelper.java @@ -66,19 +66,22 @@ public class SqmMappingModelHelper { public static SqmPathSource resolveSqmKeyPathSource( DomainType valueDomainType, - Bindable.BindableType jpaBindableType) { + Bindable.BindableType jpaBindableType, + boolean isGeneric) { return resolveSqmPathSource( CollectionPart.Nature.INDEX.getName(), valueDomainType, - jpaBindableType + jpaBindableType, + isGeneric ); } public static SqmPathSource resolveSqmPathSource( String name, DomainType valueDomainType, - Bindable.BindableType jpaBindableType) { - return resolveSqmPathSource( name, null, valueDomainType, jpaBindableType, false ); + Bindable.BindableType jpaBindableType, + boolean isGeneric) { + return resolveSqmPathSource( name, null, valueDomainType, jpaBindableType, isGeneric ); } public static SqmPathSource resolveSqmPathSource( @@ -93,7 +96,8 @@ public class SqmMappingModelHelper { name, pathModel, (BasicDomainType) valueDomainType, - jpaBindableType + jpaBindableType, + isGeneric ); } @@ -121,7 +125,8 @@ public class SqmMappingModelHelper { name, pathModel, (EntityDomainType) valueDomainType, - jpaBindableType + jpaBindableType, + isGeneric ); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPath.java index 2cb22677ed..48f09f058c 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPath.java @@ -14,7 +14,9 @@ import java.util.Map; import java.util.function.Consumer; import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; +import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.PersistentAttribute; import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.SqmExpressible; @@ -140,6 +142,17 @@ public abstract class AbstractSqmPath extends AbstractSqmExpression implem @Override public SqmPathSource getResolvedModel() { + final DomainType lhsType; + final SqmPathSource pathSource = getReferencedPathSource(); + if ( pathSource.isGeneric() && ( lhsType = getLhs().getReferencedPathSource() + .getSqmPathType() ) instanceof ManagedDomainType ) { + final PersistentAttribute concreteAttribute = ( (ManagedDomainType) lhsType ).findConcreteGenericAttribute( + pathSource.getPathName() + ); + if ( concreteAttribute != null ) { + return (SqmPathSource) concreteAttribute; + } + } return getModel(); } @@ -163,9 +176,7 @@ public abstract class AbstractSqmPath extends AbstractSqmExpression implem @Override @SuppressWarnings("unchecked") public SqmPath get(String attributeName) { - - final SqmPathSource subNavigable = getReferencedPathSource().getSubPathSource( attributeName ); - + final SqmPathSource subNavigable = getResolvedModel().getSubPathSource( attributeName ); return resolvePath( attributeName, subNavigable ); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmCteRoot.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmCteRoot.java index 16b585ff17..f4fc1553f6 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmCteRoot.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmCteRoot.java @@ -90,6 +90,11 @@ public class SqmCteRoot extends SqmRoot implements JpaRoot { return null; } + @Override + public SqmPathSource getResolvedModel() { + return getReferencedPathSource(); + } + @Override public SqmCorrelatedRoot createCorrelation() { throw new UnsupportedOperationException(); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmDerivedRoot.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmDerivedRoot.java index a886277ad5..c5ce71316c 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmDerivedRoot.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmDerivedRoot.java @@ -92,6 +92,11 @@ public class SqmDerivedRoot extends SqmRoot implements JpaDerivedRoot { return null; } + @Override + public SqmPathSource getResolvedModel() { + return getReferencedPathSource(); + } + @Override public SqmCorrelatedRoot createCorrelation() { throw new UnsupportedOperationException(); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmEmbeddedValuedSimplePath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmEmbeddedValuedSimplePath.java index 093bb09f28..c707925cb0 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmEmbeddedValuedSimplePath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmEmbeddedValuedSimplePath.java @@ -6,12 +6,8 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType; -import org.hibernate.metamodel.model.domain.ManagedDomainType; -import org.hibernate.metamodel.model.domain.internal.CompositeSqmPathSource; -import org.hibernate.spi.NavigablePath; import org.hibernate.query.PathException; import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.sqm.NodeBuilder; @@ -19,6 +15,7 @@ import org.hibernate.query.sqm.SemanticQueryWalker; import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.tree.SqmCopyContext; +import org.hibernate.spi.NavigablePath; import org.hibernate.type.descriptor.java.JavaType; /** @@ -80,29 +77,6 @@ public class SqmEmbeddedValuedSimplePath return sqmPath; } - @Override - public SqmPath get(String attributeName) { - final SqmPathSource subNavigable = getResolvedModel().getSubPathSource( attributeName ); - return resolvePath( attributeName, subNavigable ); - } - - @Override - public SqmPathSource getResolvedModel() { - final DomainType lhsType; - final SqmPathSource pathSource = getReferencedPathSource(); - if ( pathSource.isGeneric() && ( lhsType = getLhs().getReferencedPathSource() - .getSqmPathType() ) instanceof ManagedDomainType ) { - //noinspection rawtypes - final SqmPathSource concreteEmbeddable = ( (ManagedDomainType) lhsType ).findConcreteEmbeddableAttribute( - pathSource.getPathName() - ); - if ( concreteEmbeddable != null ) { - return concreteEmbeddable; - } - } - return getModel(); - } - @Override public X accept(SemanticQueryWalker walker) { return walker.visitEmbeddableValuedPath( this ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPolymorphicRootDescriptor.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPolymorphicRootDescriptor.java index cf389d9744..681d2feb92 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPolymorphicRootDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPolymorphicRootDescriptor.java @@ -210,7 +210,7 @@ public class SqmPolymorphicRootDescriptor implements EntityDomainType { } @Override - public SingularPersistentAttribute findConcreteEmbeddableAttribute(String name) { + public PersistentAttribute findConcreteGenericAttribute(String name) { return null; } @@ -230,7 +230,7 @@ public class SqmPolymorphicRootDescriptor implements EntityDomainType { } @Override - public SingularPersistentAttribute findDeclaredConcreteEmbeddableAttribute(String name) { + public PersistentAttribute findDeclaredConcreteGenericAttribute(String name) { return null; }