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() );
}
if ( value instanceof Component ) {
actualProperty.setGenericEmbeddable( true );
final Component component = ( (Component) value );
final Iterator<Property> propertyIterator = component.getPropertyIterator();
while ( propertyIterator.hasNext() ) {

View File

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

View File

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

View File

@ -420,20 +420,26 @@ public class MetadataContext {
private void applyIdMetadata(PersistentClass persistentClass, IdentifiableDomainType<?> identifiableType) {
if ( persistentClass.hasIdentifierProperty() ) {
final Property declaredIdentifierProperty = persistentClass.getDeclaredIdentifierProperty();
//noinspection rawtypes
final AttributeContainer attributeContainer = (AttributeContainer) identifiableType;
if ( declaredIdentifierProperty != null ) {
final SingularPersistentAttribute<?, Object> idAttribute = attributeFactory.buildIdAttribute(
identifiableType,
declaredIdentifierProperty
);
//noinspection unchecked rawtypes
( ( AttributeContainer) identifiableType ).getInFlightAccess().applyIdAttribute( idAttribute );
//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
attributeFactory.buildIdAttribute( identifiableType, persistentClass.getIdentifierProperty() );
final SingularPersistentAttribute<?, Object> concreteEmbeddable = attributeFactory.buildIdAttribute(
identifiableType,
persistentClass.getIdentifierProperty()
);
//noinspection unchecked
attributeContainer.getInFlightAccess().addConcreteEmbeddableAttribute( concreteEmbeddable );
}
}
else {

View File

@ -424,7 +424,8 @@ public abstract class AbstractIdentifiableType<J>
return new EmbeddedSqmPathSource<>(
EntityIdentifierMapping.ROLE_LOCAL_NAME,
compositeType,
Bindable.BindableType.SINGULAR_ATTRIBUTE
Bindable.BindableType.SINGULAR_ATTRIBUTE,
id.isGeneric()
);
}
}
@ -441,7 +442,8 @@ public abstract class AbstractIdentifiableType<J>
return new EmbeddedSqmPathSource<>(
EntityIdentifierMapping.ROLE_LOCAL_NAME,
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 volatile Map<String, PluralPersistentAttribute<J, ?, ?>> declaredPluralAttributes ;
private volatile Map<String, SingularPersistentAttribute<J, ?>> declaredConcreteEmbeddedAttributes;
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
@ -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
public void finishUp() {
inFlightAccess = null;

View File

@ -59,10 +59,12 @@ public interface ManagedDomainType<J> extends SqmExpressible<J>, DomainType<J>,
SingularPersistentAttribute<? super J,?> findSingularAttribute(String name);
PluralPersistentAttribute<? super J, ?,?> findPluralAttribute(String name);
SingularPersistentAttribute<? super J, ?> findConcreteEmbeddableAttribute(String name);
PersistentAttribute<J,?> findDeclaredAttribute(String name);
SingularPersistentAttribute<? super J, ?> findDeclaredSingularAttribute(String name);
PluralPersistentAttribute<? super J, ?, ?> findDeclaredPluralAttribute(String name);
SingularPersistentAttribute<? super J, ?> findDeclaredConcreteEmbeddableAttribute(String name);
SubGraphImplementor<J> makeSubGraph();
<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
*/

View File

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

View File

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

View File

@ -86,4 +86,11 @@ public interface SqmPathSource<J> extends SqmExpressible<J>, Bindable<J>, SqmExp
default SqmExpressible<J> getExpressible() {
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,
DomainType<J> valueDomainType,
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<?> ) {
return new BasicSqmPathSource<>(
@ -99,7 +107,8 @@ public class SqmMappingModelHelper {
return new EmbeddedSqmPathSource<>(
name,
(EmbeddableDomainType<J>) valueDomainType,
jpaBindableType
jpaBindableType,
isGeneric
);
}

View File

@ -6,8 +6,11 @@
*/
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;
@ -77,6 +80,24 @@ public class SqmEmbeddedValuedSimplePath<T>
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
public <X> X accept(SemanticQueryWalker<X> walker) {
return walker.visitEmbeddableValuedPath( this );

View File

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