HHH-16188 Register concrete embeddable type to use when creating SqmPath

This commit is contained in:
Marco Belladelli 2023-02-28 10:26:44 +01:00 committed by Christian Beikov
parent bec951018b
commit b198259cef
14 changed files with 131 additions and 10 deletions

View File

@ -320,6 +320,7 @@ public class ClassPropertyHolder extends AbstractPropertyHolder {
setTypeName( value, inferredData.getTypeName() ); setTypeName( value, inferredData.getTypeName() );
} }
if ( value instanceof Component ) { if ( value instanceof Component ) {
actualProperty.setGenericEmbeddable( true );
final Component component = ( (Component) value ); final Component component = ( (Component) value );
final Iterator<Property> propertyIterator = component.getPropertyIterator(); final Iterator<Property> propertyIterator = component.getPropertyIterator();
while ( propertyIterator.hasNext() ) { while ( propertyIterator.hasNext() ) {

View File

@ -57,6 +57,7 @@ public class Property implements Serializable, MetaAttributable {
private java.util.Map metaAttributes; private java.util.Map metaAttributes;
private PersistentClass persistentClass; private PersistentClass persistentClass;
private boolean naturalIdentifier; private boolean naturalIdentifier;
private boolean genericEmbeddable;
private boolean lob; private boolean lob;
private java.util.List<CallbackDefinition> callbackDefinitions; private java.util.List<CallbackDefinition> callbackDefinitions;
private String returnedClassName; private String returnedClassName;
@ -417,6 +418,14 @@ public class Property implements Serializable, MetaAttributable {
this.naturalIdentifier = naturalIdentifier; this.naturalIdentifier = naturalIdentifier;
} }
public boolean isGenericEmbeddable() {
return genericEmbeddable;
}
public void setGenericEmbeddable(boolean genericEmbeddable) {
this.genericEmbeddable = genericEmbeddable;
}
public boolean isLob() { public boolean isLob() {
return lob; return lob;
} }
@ -473,6 +482,7 @@ public class Property implements Serializable, MetaAttributable {
property.setMetaAttributes( getMetaAttributes() ); property.setMetaAttributes( getMetaAttributes() );
property.setPersistentClass( getPersistentClass() ); property.setPersistentClass( getPersistentClass() );
property.setNaturalIdentifier( isNaturalIdentifier() ); property.setNaturalIdentifier( isNaturalIdentifier() );
property.setGeneric( isGeneric() );
property.setLob( isLob() ); property.setLob( isLob() );
property.addCallbackDefinitions( getCallbackDefinitions() ); property.addCallbackDefinitions( getCallbackDefinitions() );
property.setReturnedClassName( getReturnedClassName() ); property.setReturnedClassName( getReturnedClassName() );

View File

@ -129,6 +129,7 @@ public class AttributeFactory {
false, false,
false, false,
property.isOptional(), property.isOptional(),
property.isGenericEmbeddable(),
metadataContext metadataContext
); );
} }
@ -176,6 +177,7 @@ public class AttributeFactory {
(SimpleDomainType<Y>) determineSimpleType( attributeMetadata.getValueContext() ), (SimpleDomainType<Y>) determineSimpleType( attributeMetadata.getValueContext() ),
attributeMetadata.getMember(), attributeMetadata.getMember(),
attributeMetadata.getAttributeClassification(), attributeMetadata.getAttributeClassification(),
property.isGenericEmbeddable(),
context context
); );
} }

View File

@ -420,20 +420,26 @@ public class MetadataContext {
private void applyIdMetadata(PersistentClass persistentClass, IdentifiableDomainType<?> identifiableType) { private void applyIdMetadata(PersistentClass persistentClass, IdentifiableDomainType<?> identifiableType) {
if ( persistentClass.hasIdentifierProperty() ) { if ( persistentClass.hasIdentifierProperty() ) {
final Property declaredIdentifierProperty = persistentClass.getDeclaredIdentifierProperty(); final Property declaredIdentifierProperty = persistentClass.getDeclaredIdentifierProperty();
//noinspection rawtypes
final AttributeContainer attributeContainer = (AttributeContainer) identifiableType;
if ( declaredIdentifierProperty != null ) { if ( declaredIdentifierProperty != null ) {
final SingularPersistentAttribute<?, Object> idAttribute = attributeFactory.buildIdAttribute( final SingularPersistentAttribute<?, Object> idAttribute = attributeFactory.buildIdAttribute(
identifiableType, identifiableType,
declaredIdentifierProperty declaredIdentifierProperty
); );
//noinspection unchecked
//noinspection unchecked rawtypes attributeContainer.getInFlightAccess().applyIdAttribute( idAttribute );
( ( AttributeContainer) identifiableType ).getInFlightAccess().applyIdAttribute( idAttribute );
} }
else if ( persistentClass.getIdentifier() instanceof Component else if ( persistentClass.getIdentifier() instanceof Component
&& persistentClass.getIdentifierProperty() != getSuperclassIdentifier( persistentClass ) ) { && persistentClass.getIdentifierProperty() != getSuperclassIdentifier( persistentClass ) ) {
// If the identifier is a generic component, we have to call buildIdAttribute anyway, // If the identifier is a generic component, we have to call buildIdAttribute anyway,
// as this will create and register the EmbeddableType for the subtype // as this will create and register the EmbeddableType for the subtype
attributeFactory.buildIdAttribute( identifiableType, persistentClass.getIdentifierProperty() ); final SingularPersistentAttribute<?, Object> concreteEmbeddable = attributeFactory.buildIdAttribute(
identifiableType,
persistentClass.getIdentifierProperty()
);
//noinspection unchecked
attributeContainer.getInFlightAccess().addConcreteEmbeddableAttribute( concreteEmbeddable );
} }
} }
else { else {

View File

@ -424,7 +424,8 @@ public abstract class AbstractIdentifiableType<J>
return new EmbeddedSqmPathSource<>( return new EmbeddedSqmPathSource<>(
EntityIdentifierMapping.ROLE_LOCAL_NAME, EntityIdentifierMapping.ROLE_LOCAL_NAME,
compositeType, compositeType,
Bindable.BindableType.SINGULAR_ATTRIBUTE Bindable.BindableType.SINGULAR_ATTRIBUTE,
id.isGeneric()
); );
} }
} }
@ -441,7 +442,8 @@ public abstract class AbstractIdentifiableType<J>
return new EmbeddedSqmPathSource<>( return new EmbeddedSqmPathSource<>(
EntityIdentifierMapping.ROLE_LOCAL_NAME, EntityIdentifierMapping.ROLE_LOCAL_NAME,
idClassType, idClassType,
Bindable.BindableType.SINGULAR_ATTRIBUTE Bindable.BindableType.SINGULAR_ATTRIBUTE,
false
); );
} }
} }

View File

@ -56,6 +56,7 @@ public abstract class AbstractManagedType<J>
private final Map<String, SingularPersistentAttribute<J, ?>> declaredSingularAttributes = new LinkedHashMap<>(); private final Map<String, SingularPersistentAttribute<J, ?>> declaredSingularAttributes = new LinkedHashMap<>();
private volatile Map<String, PluralPersistentAttribute<J, ?, ?>> declaredPluralAttributes ; private volatile Map<String, PluralPersistentAttribute<J, ?, ?>> declaredPluralAttributes ;
private volatile Map<String, SingularPersistentAttribute<J, ?>> declaredConcreteEmbeddedAttributes;
private final List<ManagedDomainType> subTypes = new ArrayList<>(); private final List<ManagedDomainType> subTypes = new ArrayList<>();
@ -464,6 +465,24 @@ public abstract class AbstractManagedType<J>
} }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Generic Embeddable attributes
@Override
public SingularPersistentAttribute<? super J, ?> findConcreteEmbeddableAttribute(String name) {
SingularPersistentAttribute<? super J, ?> attribute = findDeclaredConcreteEmbeddableAttribute( name );
if ( attribute == null && getSuperType() != null ) {
attribute = getSuperType().findDeclaredConcreteEmbeddableAttribute( name );
}
return attribute;
}
@Override
public SingularPersistentAttribute<? super J, ?> findDeclaredConcreteEmbeddableAttribute(String name) {
return declaredConcreteEmbeddedAttributes == null ? null : declaredConcreteEmbeddedAttributes.get( name );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Bags // Bags
@ -740,6 +759,14 @@ public abstract class AbstractManagedType<J>
} }
} }
@Override
public void addConcreteEmbeddableAttribute(SingularPersistentAttribute<J, ?> attribute) {
if ( declaredConcreteEmbeddedAttributes == null ) {
declaredConcreteEmbeddedAttributes = new HashMap<>();
}
declaredConcreteEmbeddedAttributes.put( attribute.getName(), attribute );
}
@Override @Override
public void finishUp() { public void finishUp() {
inFlightAccess = null; inFlightAccess = null;

View File

@ -59,10 +59,12 @@ public interface ManagedDomainType<J> extends SqmExpressible<J>, DomainType<J>,
SingularPersistentAttribute<? super J,?> findSingularAttribute(String name); SingularPersistentAttribute<? super J,?> findSingularAttribute(String name);
PluralPersistentAttribute<? super J, ?,?> findPluralAttribute(String name); PluralPersistentAttribute<? super J, ?,?> findPluralAttribute(String name);
SingularPersistentAttribute<? super J, ?> findConcreteEmbeddableAttribute(String name);
PersistentAttribute<J,?> findDeclaredAttribute(String name); PersistentAttribute<J,?> findDeclaredAttribute(String name);
SingularPersistentAttribute<? super J, ?> findDeclaredSingularAttribute(String name); SingularPersistentAttribute<? super J, ?> findDeclaredSingularAttribute(String name);
PluralPersistentAttribute<? super J, ?, ?> findDeclaredPluralAttribute(String name); PluralPersistentAttribute<? super J, ?, ?> findDeclaredPluralAttribute(String name);
SingularPersistentAttribute<? super J, ?> findDeclaredConcreteEmbeddableAttribute(String name);
SubGraphImplementor<J> makeSubGraph(); SubGraphImplementor<J> makeSubGraph();
<S extends J> SubGraphImplementor<S> makeSubGraph(Class<S> subClassType); <S extends J> SubGraphImplementor<S> makeSubGraph(Class<S> subClassType);

View File

@ -66,6 +66,12 @@ public interface AttributeContainer<J> {
); );
} }
default void addConcreteEmbeddableAttribute(SingularPersistentAttribute<J, ?> idAttribute) {
throw new UnsupportedMappingException(
"AttributeContainer [" + getClass().getName() + "] does not generic embeddables"
);
}
/** /**
* Called when configuration of the type is complete * Called when configuration of the type is complete
*/ */

View File

@ -7,10 +7,10 @@
package org.hibernate.metamodel.model.domain.internal; package org.hibernate.metamodel.model.domain.internal;
import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
import org.hibernate.spi.NavigablePath;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.spi.NavigablePath;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -18,12 +18,15 @@ import org.hibernate.query.sqm.tree.domain.SqmPath;
public class EmbeddedSqmPathSource<J> public class EmbeddedSqmPathSource<J>
extends AbstractSqmPathSource<J> extends AbstractSqmPathSource<J>
implements CompositeSqmPathSource<J> { implements CompositeSqmPathSource<J> {
private final boolean isGeneric;
public EmbeddedSqmPathSource( public EmbeddedSqmPathSource(
String localPathName, String localPathName,
EmbeddableDomainType<J> domainType, EmbeddableDomainType<J> domainType,
BindableType jpaBindableType) { BindableType jpaBindableType,
boolean isGeneric) {
super( localPathName, domainType, jpaBindableType ); super( localPathName, domainType, jpaBindableType );
this.isGeneric = isGeneric;
} }
@Override @Override
@ -37,6 +40,11 @@ public class EmbeddedSqmPathSource<J>
return (SqmPathSource<?>) getSqmPathType().findAttribute( name ); return (SqmPathSource<?>) getSqmPathType().findAttribute( name );
} }
@Override
public boolean isGeneric() {
return isGeneric;
}
@Override @Override
public SqmPath<J> createSqmPath(SqmPath<?> lhs, SqmPathSource<?> intermediatePathSource) { public SqmPath<J> createSqmPath(SqmPath<?> lhs, SqmPathSource<?> intermediatePathSource) {
final NavigablePath navigablePath; final NavigablePath navigablePath;

View File

@ -59,6 +59,7 @@ public class SingularAttributeImpl<D,J>
boolean isIdentifier, boolean isIdentifier,
boolean isVersion, boolean isVersion,
boolean isOptional, boolean isOptional,
boolean isGeneric,
MetadataContext metadataContext) { MetadataContext metadataContext) {
super( super(
declaringType, declaringType,
@ -77,7 +78,8 @@ public class SingularAttributeImpl<D,J>
this.sqmPathSource = SqmMappingModelHelper.resolveSqmPathSource( this.sqmPathSource = SqmMappingModelHelper.resolveSqmPathSource(
name, name,
attributeType, attributeType,
BindableType.SINGULAR_ATTRIBUTE BindableType.SINGULAR_ATTRIBUTE,
isGeneric
); );
} }
@ -121,6 +123,11 @@ public class SingularAttributeImpl<D,J>
return sqmPathSource.findSubPathSource( name ); return sqmPathSource.findSubPathSource( name );
} }
@Override
public boolean isGeneric() {
return sqmPathSource.isGeneric();
}
@Override @Override
public SqmAttributeJoin<D,J> createSqmJoin( public SqmAttributeJoin<D,J> createSqmJoin(
SqmFrom lhs, SqmFrom lhs,
@ -154,6 +161,7 @@ public class SingularAttributeImpl<D,J>
SimpleDomainType<J> attributeType, SimpleDomainType<J> attributeType,
Member member, Member member,
AttributeClassification attributeClassification, AttributeClassification attributeClassification,
boolean isGeneric,
MetadataContext metadataContext) { MetadataContext metadataContext) {
super( super(
declaringType, declaringType,
@ -164,6 +172,7 @@ public class SingularAttributeImpl<D,J>
true, true,
false, false,
false, false,
isGeneric,
metadataContext metadataContext
); );
} }
@ -204,6 +213,7 @@ public class SingularAttributeImpl<D,J>
false, false,
true, true,
false, false,
false,
metadataContext metadataContext
); );
} }

View File

@ -86,4 +86,11 @@ public interface SqmPathSource<J> extends SqmExpressible<J>, Bindable<J>, SqmExp
default SqmExpressible<J> getExpressible() { default SqmExpressible<J> getExpressible() {
return (SqmExpressible<J>) getSqmPathType(); return (SqmExpressible<J>) getSqmPathType();
} }
/**
* Indicates if this path source is generically typed
*/
default boolean isGeneric() {
return false;
}
} }

View File

@ -78,6 +78,14 @@ public class SqmMappingModelHelper {
String name, String name,
DomainType<J> valueDomainType, DomainType<J> valueDomainType,
Bindable.BindableType jpaBindableType) { Bindable.BindableType jpaBindableType) {
return resolveSqmPathSource( name, valueDomainType, jpaBindableType, false );
}
public static <J> SqmPathSource<J> resolveSqmPathSource(
String name,
DomainType<J> valueDomainType,
Bindable.BindableType jpaBindableType,
boolean isGeneric) {
if ( valueDomainType instanceof BasicDomainType<?> ) { if ( valueDomainType instanceof BasicDomainType<?> ) {
return new BasicSqmPathSource<>( return new BasicSqmPathSource<>(
@ -99,7 +107,8 @@ public class SqmMappingModelHelper {
return new EmbeddedSqmPathSource<>( return new EmbeddedSqmPathSource<>(
name, name,
(EmbeddableDomainType<J>) valueDomainType, (EmbeddableDomainType<J>) valueDomainType,
jpaBindableType jpaBindableType,
isGeneric
); );
} }

View File

@ -6,8 +6,11 @@
*/ */
package org.hibernate.query.sqm.tree.domain; 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.EmbeddableDomainType;
import org.hibernate.metamodel.model.domain.EntityDomainType; 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.spi.NavigablePath;
import org.hibernate.query.PathException; import org.hibernate.query.PathException;
import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.hql.spi.SqmCreationState;
@ -77,6 +80,24 @@ public class SqmEmbeddedValuedSimplePath<T>
return sqmPath; return sqmPath;
} }
@Override
public SqmPath<?> get(String attributeName) {
final DomainType<?> lhsType;
final SqmPathSource<T> pathSource = getReferencedPathSource();
if ( pathSource.isGeneric() && ( lhsType = getLhs().getReferencedPathSource()
.getSqmPathType() ) instanceof ManagedDomainType ) {
//noinspection rawtypes
final SqmPathSource<?> concreteEmbeddable = ( (ManagedDomainType) lhsType ).findConcreteEmbeddableAttribute(
pathSource.getPathName()
);
if ( concreteEmbeddable != null ) {
final SqmPathSource<?> subNavigable = concreteEmbeddable.getSubPathSource( attributeName );
return resolvePath( attributeName, subNavigable );
}
}
return super.get( attributeName );
}
@Override @Override
public <X> X accept(SemanticQueryWalker<X> walker) { public <X> X accept(SemanticQueryWalker<X> walker) {
return walker.visitEmbeddableValuedPath( this ); return walker.visitEmbeddableValuedPath( this );

View File

@ -209,6 +209,11 @@ public class SqmPolymorphicRootDescriptor<T> implements EntityDomainType<T> {
return (PluralPersistentAttribute<? super T, ?, ?>) findAttribute( name ); return (PluralPersistentAttribute<? super T, ?, ?>) findAttribute( name );
} }
@Override
public SingularPersistentAttribute<? super T, ?> findConcreteEmbeddableAttribute(String name) {
return null;
}
@Override @Override
public PersistentAttribute<T, ?> findDeclaredAttribute(String name) { public PersistentAttribute<T, ?> findDeclaredAttribute(String name) {
return null; return null;
@ -224,6 +229,11 @@ public class SqmPolymorphicRootDescriptor<T> implements EntityDomainType<T> {
return null; return null;
} }
@Override
public SingularPersistentAttribute<? super T, ?> findDeclaredConcreteEmbeddableAttribute(String name) {
return null;
}
@Override @Override
public Set<Attribute<? super T, ?>> getAttributes() { public Set<Attribute<? super T, ?>> getAttributes() {
//noinspection unchecked //noinspection unchecked