HHH-16378 Handle non-embeddable generic attribute paths
This commit is contained in:
parent
9d6499536b
commit
a24081a096
|
@ -23,6 +23,7 @@ import org.hibernate.mapping.Map;
|
||||||
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;
|
||||||
|
import org.hibernate.mapping.SimpleValue;
|
||||||
import org.hibernate.mapping.Value;
|
import org.hibernate.mapping.Value;
|
||||||
import org.hibernate.metamodel.AttributeClassification;
|
import org.hibernate.metamodel.AttributeClassification;
|
||||||
import org.hibernate.metamodel.RepresentationMode;
|
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.AbstractIdentifiableType;
|
||||||
import org.hibernate.metamodel.model.domain.DomainType;
|
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.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.PersistentAttribute;
|
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||||
|
@ -116,7 +118,11 @@ public class AttributeFactory {
|
||||||
|
|
||||||
if ( attributeMetadata instanceof PluralAttributeMetadata ) {
|
if ( attributeMetadata instanceof PluralAttributeMetadata ) {
|
||||||
//noinspection rawtypes
|
//noinspection rawtypes
|
||||||
return PluralAttributeBuilder.build( (PluralAttributeMetadata) attributeMetadata, metadataContext );
|
return PluralAttributeBuilder.build(
|
||||||
|
(PluralAttributeMetadata) attributeMetadata,
|
||||||
|
property.isGeneric(),
|
||||||
|
metadataContext
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final SingularAttributeMetadata<X, Y> singularAttributeMetadata = (SingularAttributeMetadata<X, Y>) attributeMetadata;
|
final SingularAttributeMetadata<X, Y> singularAttributeMetadata = (SingularAttributeMetadata<X, Y>) attributeMetadata;
|
||||||
|
@ -221,7 +227,18 @@ public class AttributeFactory {
|
||||||
public static <Y> DomainType<Y> determineSimpleType(ValueContext typeContext, MetadataContext context) {
|
public static <Y> DomainType<Y> determineSimpleType(ValueContext typeContext, MetadataContext context) {
|
||||||
switch ( typeContext.getValueClassification() ) {
|
switch ( typeContext.getValueClassification() ) {
|
||||||
case BASIC: {
|
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: {
|
case ENTITY: {
|
||||||
final org.hibernate.type.Type type = typeContext.getHibernateValue().getType();
|
final org.hibernate.type.Type type = typeContext.getHibernateValue().getType();
|
||||||
|
|
|
@ -273,7 +273,7 @@ public class MetadataContext {
|
||||||
|
|
||||||
applyIdMetadata( safeMapping, jpaMapping );
|
applyIdMetadata( safeMapping, jpaMapping );
|
||||||
applyVersionAttribute( safeMapping, jpaMapping );
|
applyVersionAttribute( safeMapping, jpaMapping );
|
||||||
applyGenericEmbeddableProperties( safeMapping, jpaMapping );
|
applyGenericProperties( safeMapping, jpaMapping );
|
||||||
|
|
||||||
for ( Property property : safeMapping.getDeclaredProperties() ) {
|
for ( Property property : safeMapping.getDeclaredProperties() ) {
|
||||||
if ( property.getValue() == safeMapping.getIdentifierMapper() ) {
|
if ( property.getValue() == safeMapping.getIdentifierMapper() ) {
|
||||||
|
@ -430,16 +430,15 @@ public class MetadataContext {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
attributeContainer.getInFlightAccess().applyIdAttribute( idAttribute );
|
attributeContainer.getInFlightAccess().applyIdAttribute( idAttribute );
|
||||||
}
|
}
|
||||||
else if ( persistentClass.getIdentifier() instanceof Component
|
final Property superclassIdentifier = getMappedSuperclassIdentifier( persistentClass );
|
||||||
&& persistentClass.getIdentifierProperty() != getSuperclassIdentifier( persistentClass ) ) {
|
if ( superclassIdentifier != null && superclassIdentifier.isGeneric() ) {
|
||||||
// If the identifier is a generic component, we have to call buildIdAttribute anyway,
|
// If the superclass identifier is generic we have to build the attribute to register the concrete type
|
||||||
// as this will create and register the EmbeddableType for the subtype
|
final SingularPersistentAttribute<?, Object> concreteIdentifier = attributeFactory.buildIdAttribute(
|
||||||
final SingularPersistentAttribute<?, Object> concreteEmbeddable = attributeFactory.buildIdAttribute(
|
|
||||||
identifiableType,
|
identifiableType,
|
||||||
persistentClass.getIdentifierProperty()
|
persistentClass.getIdentifierProperty()
|
||||||
);
|
);
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
attributeContainer.getInFlightAccess().addConcreteEmbeddableAttribute( concreteEmbeddable );
|
attributeContainer.getInFlightAccess().addConcreteGenericAttribute( concreteIdentifier );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -489,30 +488,14 @@ public class MetadataContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Property getSuperclassIdentifier(PersistentClass persistentClass) {
|
private Property getMappedSuperclassIdentifier(PersistentClass persistentClass) {
|
||||||
final Property declaredIdentifierProperty = persistentClass.getDeclaredIdentifierProperty();
|
MappedSuperclass mappedSuperclass = getMappedSuperclass( persistentClass );
|
||||||
if ( declaredIdentifierProperty != null ) {
|
while ( mappedSuperclass != null ) {
|
||||||
return declaredIdentifierProperty;
|
final Property declaredIdentifierProperty = mappedSuperclass.getDeclaredIdentifierProperty();
|
||||||
}
|
if ( declaredIdentifierProperty != null ) {
|
||||||
if ( persistentClass.getSuperMappedSuperclass() != null ) {
|
return declaredIdentifierProperty;
|
||||||
return getSuperclassIdentifier( persistentClass.getSuperMappedSuperclass() );
|
}
|
||||||
}
|
mappedSuperclass = getMappedSuperclass( mappedSuperclass );
|
||||||
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() );
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -573,20 +556,15 @@ public class MetadataContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private <X> void applyGenericEmbeddableProperties(
|
private <X> void applyGenericProperties(PersistentClass persistentClass, EntityDomainType<X> entityType) {
|
||||||
PersistentClass persistentClass,
|
|
||||||
EntityDomainType<X> entityType) {
|
|
||||||
MappedSuperclass mappedSuperclass = getMappedSuperclass( persistentClass );
|
MappedSuperclass mappedSuperclass = getMappedSuperclass( persistentClass );
|
||||||
while ( mappedSuperclass != null ) {
|
while ( mappedSuperclass != null ) {
|
||||||
for ( Property superclassProperty : mappedSuperclass.getDeclaredProperties() ) {
|
for ( Property superclassProperty : mappedSuperclass.getDeclaredProperties() ) {
|
||||||
if ( superclassProperty.isGeneric() && superclassProperty.isComposite() ) {
|
if ( superclassProperty.isGeneric() ) {
|
||||||
final Property property = persistentClass.getProperty( superclassProperty.getName() );
|
final Property property = persistentClass.getProperty( superclassProperty.getName() );
|
||||||
final SingularPersistentAttribute<X, ?> attribute = (SingularPersistentAttribute<X, ?>) attributeFactory.buildAttribute(
|
final PersistentAttribute<X, ?> attribute = attributeFactory.buildAttribute( entityType, property );
|
||||||
entityType,
|
//noinspection unchecked
|
||||||
property
|
( (AttributeContainer<X>) entityType ).getInFlightAccess().addConcreteGenericAttribute( attribute );
|
||||||
);
|
|
||||||
//noinspection unchecked rawtypes
|
|
||||||
( (AttributeContainer) entityType ).getInFlightAccess().addConcreteEmbeddableAttribute( attribute );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mappedSuperclass = getMappedSuperclass( mappedSuperclass );
|
mappedSuperclass = getMappedSuperclass( mappedSuperclass );
|
||||||
|
|
|
@ -416,7 +416,8 @@ public abstract class AbstractIdentifiableType<J>
|
||||||
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
||||||
(SqmPathSource) id,
|
(SqmPathSource) id,
|
||||||
(BasicDomainType<?>) type,
|
(BasicDomainType<?>) type,
|
||||||
Bindable.BindableType.SINGULAR_ATTRIBUTE
|
Bindable.BindableType.SINGULAR_ATTRIBUTE,
|
||||||
|
id.isGeneric()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -56,7 +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 volatile Map<String, PersistentAttribute<J, ?>> declaredConcreteGenericAttributes;
|
||||||
|
|
||||||
private final List<ManagedDomainType> subTypes = new ArrayList<>();
|
private final List<ManagedDomainType> subTypes = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -466,20 +466,20 @@ public abstract class AbstractManagedType<J>
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Generic Embeddable attributes
|
// Generic attributes
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SingularPersistentAttribute<? super J, ?> findConcreteEmbeddableAttribute(String name) {
|
public PersistentAttribute<? super J, ?> findConcreteGenericAttribute(String name) {
|
||||||
SingularPersistentAttribute<? super J, ?> attribute = findDeclaredConcreteEmbeddableAttribute( name );
|
PersistentAttribute<? super J, ?> attribute = findDeclaredConcreteGenericAttribute( name );
|
||||||
if ( attribute == null && getSuperType() != null ) {
|
if ( attribute == null && getSuperType() != null ) {
|
||||||
attribute = getSuperType().findDeclaredConcreteEmbeddableAttribute( name );
|
attribute = getSuperType().findDeclaredConcreteGenericAttribute( name );
|
||||||
}
|
}
|
||||||
return attribute;
|
return attribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SingularPersistentAttribute<? super J, ?> findDeclaredConcreteEmbeddableAttribute(String name) {
|
public PersistentAttribute<? super J, ?> findDeclaredConcreteGenericAttribute(String name) {
|
||||||
return declaredConcreteEmbeddedAttributes == null ? null : declaredConcreteEmbeddedAttributes.get( name );
|
return declaredConcreteGenericAttributes == null ? null : declaredConcreteGenericAttributes.get( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -760,11 +760,11 @@ public abstract class AbstractManagedType<J>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addConcreteEmbeddableAttribute(SingularPersistentAttribute<J, ?> attribute) {
|
public void addConcreteGenericAttribute(PersistentAttribute<J, ?> attribute) {
|
||||||
if ( declaredConcreteEmbeddedAttributes == null ) {
|
if ( declaredConcreteGenericAttributes == null ) {
|
||||||
declaredConcreteEmbeddedAttributes = new HashMap<>();
|
declaredConcreteGenericAttributes = new HashMap<>();
|
||||||
}
|
}
|
||||||
declaredConcreteEmbeddedAttributes.put( attribute.getName(), attribute );
|
declaredConcreteGenericAttributes.put( attribute.getName(), attribute );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -59,12 +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<? super J, ?> findConcreteGenericAttribute(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);
|
PersistentAttribute<? super J, ?> findDeclaredConcreteGenericAttribute(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);
|
||||||
|
|
|
@ -54,7 +54,8 @@ public abstract class AbstractPluralAttribute<D, C, E>
|
||||||
this.elementPathSource = SqmMappingModelHelper.resolveSqmPathSource(
|
this.elementPathSource = SqmMappingModelHelper.resolveSqmPathSource(
|
||||||
CollectionPart.Nature.ELEMENT.getName(),
|
CollectionPart.Nature.ELEMENT.getName(),
|
||||||
builder.getValueType(),
|
builder.getValueType(),
|
||||||
BindableType.PLURAL_ATTRIBUTE
|
BindableType.PLURAL_ATTRIBUTE,
|
||||||
|
builder.isGeneric()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ public abstract class AbstractPluralAttribute<D, C, E>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPathSource<?> getIntermediatePathSource(SqmPathSource<?> pathSource) {
|
public SqmPathSource<?> getIntermediatePathSource(SqmPathSource<?> pathSource) {
|
||||||
return pathSource == elementPathSource ? null : elementPathSource;
|
return pathSource.getPathName().equals( elementPathSource.getPathName() ) ? null : elementPathSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -154,4 +155,9 @@ public abstract class AbstractPluralAttribute<D, C, E>
|
||||||
lhs.nodeBuilder()
|
lhs.nodeBuilder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isGeneric() {
|
||||||
|
return elementPathSource.isGeneric();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,8 @@ public class AnyMappingSqmPathSource<J> extends AbstractSqmPathSource<J> {
|
||||||
"id",
|
"id",
|
||||||
null,
|
null,
|
||||||
(BasicDomainType<?>) domainType.getKeyType(),
|
(BasicDomainType<?>) domainType.getKeyType(),
|
||||||
SINGULAR_ATTRIBUTE
|
SINGULAR_ATTRIBUTE,
|
||||||
|
false
|
||||||
);
|
);
|
||||||
discriminatorPathSource = new AnyDiscriminatorSqmPathSource<>(
|
discriminatorPathSource = new AnyDiscriminatorSqmPathSource<>(
|
||||||
localPathName,
|
localPathName,
|
||||||
|
|
|
@ -66,7 +66,7 @@ public interface AttributeContainer<J> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
default void addConcreteEmbeddableAttribute(SingularPersistentAttribute<J, ?> idAttribute) {
|
default void addConcreteGenericAttribute(PersistentAttribute<J, ?> idAttribute) {
|
||||||
throw new UnsupportedMappingException(
|
throw new UnsupportedMappingException(
|
||||||
"AttributeContainer [" + getClass().getName() + "] does not generic embeddables"
|
"AttributeContainer [" + getClass().getName() + "] does not generic embeddables"
|
||||||
);
|
);
|
||||||
|
|
|
@ -19,13 +19,16 @@ import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
public class BasicSqmPathSource<J>
|
public class BasicSqmPathSource<J>
|
||||||
extends AbstractSqmPathSource<J>
|
extends AbstractSqmPathSource<J>
|
||||||
implements ReturnableType<J> {
|
implements ReturnableType<J> {
|
||||||
|
private final boolean isGeneric;
|
||||||
|
|
||||||
public BasicSqmPathSource(
|
public BasicSqmPathSource(
|
||||||
String localPathName,
|
String localPathName,
|
||||||
SqmPathSource<J> pathModel,
|
SqmPathSource<J> pathModel,
|
||||||
BasicDomainType<J> domainType,
|
BasicDomainType<J> domainType,
|
||||||
BindableType jpaBindableType) {
|
BindableType jpaBindableType,
|
||||||
|
boolean isGeneric) {
|
||||||
super( localPathName, pathModel, domainType, jpaBindableType );
|
super( localPathName, pathModel, domainType, jpaBindableType );
|
||||||
|
this.isGeneric = isGeneric;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -66,6 +69,11 @@ public class BasicSqmPathSource<J>
|
||||||
return getExpressibleJavaType().getJavaTypeClass();
|
return getExpressibleJavaType().getJavaTypeClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isGeneric() {
|
||||||
|
return isGeneric;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "BasicSqmPathSource(" +
|
return "BasicSqmPathSource(" +
|
||||||
|
|
|
@ -21,12 +21,16 @@ import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class EntitySqmPathSource<J> extends AbstractSqmPathSource<J> implements SqmJoinable<Object, J> {
|
public class EntitySqmPathSource<J> extends AbstractSqmPathSource<J> implements SqmJoinable<Object, J> {
|
||||||
|
private final boolean isGeneric;
|
||||||
|
|
||||||
public EntitySqmPathSource(
|
public EntitySqmPathSource(
|
||||||
String localPathName,
|
String localPathName,
|
||||||
SqmPathSource<J> pathModel,
|
SqmPathSource<J> pathModel,
|
||||||
EntityDomainType<J> domainType,
|
EntityDomainType<J> domainType,
|
||||||
BindableType jpaBindableType) {
|
BindableType jpaBindableType,
|
||||||
|
boolean isGeneric) {
|
||||||
super( localPathName, pathModel, domainType, jpaBindableType );
|
super( localPathName, pathModel, domainType, jpaBindableType );
|
||||||
|
this.isGeneric = isGeneric;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -41,6 +45,11 @@ public class EntitySqmPathSource<J> extends AbstractSqmPathSource<J> implements
|
||||||
return sqmPathType.findSubPathSource( name );
|
return sqmPathType.findSubPathSource( 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;
|
||||||
|
|
|
@ -31,7 +31,8 @@ class ListAttributeImpl<X, E> extends AbstractPluralAttribute<X, List<E>, E> imp
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
this.indexPathSource = (SqmPathSource<Integer>) SqmMappingModelHelper.resolveSqmKeyPathSource(
|
this.indexPathSource = (SqmPathSource<Integer>) SqmMappingModelHelper.resolveSqmKeyPathSource(
|
||||||
builder.getListIndexOrMapKeyType(),
|
builder.getListIndexOrMapKeyType(),
|
||||||
BindableType.PLURAL_ATTRIBUTE
|
BindableType.PLURAL_ATTRIBUTE,
|
||||||
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +62,9 @@ class ListAttributeImpl<X, E> extends AbstractPluralAttribute<X, List<E>, E> imp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPathSource<?> getIntermediatePathSource(SqmPathSource<?> pathSource) {
|
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
|
@Override
|
||||||
|
|
|
@ -31,7 +31,8 @@ class MapAttributeImpl<X, K, V> extends AbstractPluralAttribute<X, Map<K, V>, V>
|
||||||
|
|
||||||
this.keyPathSource = SqmMappingModelHelper.resolveSqmKeyPathSource(
|
this.keyPathSource = SqmMappingModelHelper.resolveSqmKeyPathSource(
|
||||||
xceBuilder.getListIndexOrMapKeyType(),
|
xceBuilder.getListIndexOrMapKeyType(),
|
||||||
BindableType.PLURAL_ATTRIBUTE
|
BindableType.PLURAL_ATTRIBUTE,
|
||||||
|
xceBuilder.isGeneric()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +72,9 @@ class MapAttributeImpl<X, K, V> extends AbstractPluralAttribute<X, Map<K, V>, V>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPathSource<?> getIntermediatePathSource(SqmPathSource<?> pathSource) {
|
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
|
@Override
|
||||||
|
|
|
@ -32,6 +32,7 @@ import static org.hibernate.metamodel.internal.AttributeFactory.determineSimpleT
|
||||||
*/
|
*/
|
||||||
public class PluralAttributeBuilder<D, C, E, K> {
|
public class PluralAttributeBuilder<D, C, E, K> {
|
||||||
private final JavaType<C> collectionJtd;
|
private final JavaType<C> collectionJtd;
|
||||||
|
private boolean isGeneric;
|
||||||
|
|
||||||
private final AttributeClassification attributeClassification;
|
private final AttributeClassification attributeClassification;
|
||||||
private final CollectionClassification collectionClassification;
|
private final CollectionClassification collectionClassification;
|
||||||
|
@ -46,6 +47,7 @@ public class PluralAttributeBuilder<D, C, E, K> {
|
||||||
|
|
||||||
public PluralAttributeBuilder(
|
public PluralAttributeBuilder(
|
||||||
JavaType<C> collectionJtd,
|
JavaType<C> collectionJtd,
|
||||||
|
boolean isGeneric,
|
||||||
AttributeClassification attributeClassification,
|
AttributeClassification attributeClassification,
|
||||||
CollectionClassification collectionClassification,
|
CollectionClassification collectionClassification,
|
||||||
DomainType<E> elementType,
|
DomainType<E> elementType,
|
||||||
|
@ -54,6 +56,7 @@ public class PluralAttributeBuilder<D, C, E, K> {
|
||||||
Property property,
|
Property property,
|
||||||
Member member) {
|
Member member) {
|
||||||
this.collectionJtd = collectionJtd;
|
this.collectionJtd = collectionJtd;
|
||||||
|
this.isGeneric = isGeneric;
|
||||||
this.attributeClassification = attributeClassification;
|
this.attributeClassification = attributeClassification;
|
||||||
this.collectionClassification = collectionClassification;
|
this.collectionClassification = collectionClassification;
|
||||||
this.elementType = elementType;
|
this.elementType = elementType;
|
||||||
|
@ -66,6 +69,7 @@ public class PluralAttributeBuilder<D, C, E, K> {
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
public static <Y, X> PersistentAttribute<X, Y> build(
|
public static <Y, X> PersistentAttribute<X, Y> build(
|
||||||
PluralAttributeMetadata<?,Y,?> attributeMetadata,
|
PluralAttributeMetadata<?,Y,?> attributeMetadata,
|
||||||
|
boolean isGeneric,
|
||||||
MetadataContext metadataContext) {
|
MetadataContext metadataContext) {
|
||||||
|
|
||||||
final JavaType<Y> attributeJtd = metadataContext.getTypeConfiguration()
|
final JavaType<Y> attributeJtd = metadataContext.getTypeConfiguration()
|
||||||
|
@ -74,6 +78,7 @@ public class PluralAttributeBuilder<D, C, E, K> {
|
||||||
|
|
||||||
final PluralAttributeBuilder builder = new PluralAttributeBuilder(
|
final PluralAttributeBuilder builder = new PluralAttributeBuilder(
|
||||||
attributeJtd,
|
attributeJtd,
|
||||||
|
isGeneric,
|
||||||
attributeMetadata.getAttributeClassification(),
|
attributeMetadata.getAttributeClassification(),
|
||||||
attributeMetadata.getCollectionClassification(),
|
attributeMetadata.getCollectionClassification(),
|
||||||
AttributeFactory.determineSimpleType(
|
AttributeFactory.determineSimpleType(
|
||||||
|
@ -155,6 +160,10 @@ public class PluralAttributeBuilder<D, C, E, K> {
|
||||||
return collectionJtd;
|
return collectionJtd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isGeneric() {
|
||||||
|
return isGeneric;
|
||||||
|
}
|
||||||
|
|
||||||
public DomainType<E> getValueType() {
|
public DomainType<E> getValueType() {
|
||||||
return elementType;
|
return elementType;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,8 +45,7 @@ public interface JpaPath<T> extends JpaExpression<T>, Path<T> {
|
||||||
<S extends T> JpaPath<S> treatAs(EntityDomainType<S> treatJavaType);
|
<S extends T> JpaPath<S> treatAs(EntityDomainType<S> treatJavaType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get this pat's actual resolved model, e.g. the
|
* Get this path's actual resolved model, i.e. the concrete type for generic attributes.
|
||||||
* concrete embeddable type for generic embeddables
|
|
||||||
*/
|
*/
|
||||||
SqmPathSource<?> getResolvedModel();
|
SqmPathSource<?> getResolvedModel();
|
||||||
|
|
||||||
|
|
|
@ -66,19 +66,22 @@ public class SqmMappingModelHelper {
|
||||||
|
|
||||||
public static <J> SqmPathSource<J> resolveSqmKeyPathSource(
|
public static <J> SqmPathSource<J> resolveSqmKeyPathSource(
|
||||||
DomainType<J> valueDomainType,
|
DomainType<J> valueDomainType,
|
||||||
Bindable.BindableType jpaBindableType) {
|
Bindable.BindableType jpaBindableType,
|
||||||
|
boolean isGeneric) {
|
||||||
return resolveSqmPathSource(
|
return resolveSqmPathSource(
|
||||||
CollectionPart.Nature.INDEX.getName(),
|
CollectionPart.Nature.INDEX.getName(),
|
||||||
valueDomainType,
|
valueDomainType,
|
||||||
jpaBindableType
|
jpaBindableType,
|
||||||
|
isGeneric
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <J> SqmPathSource<J> resolveSqmPathSource(
|
public static <J> SqmPathSource<J> resolveSqmPathSource(
|
||||||
String name,
|
String name,
|
||||||
DomainType<J> valueDomainType,
|
DomainType<J> valueDomainType,
|
||||||
Bindable.BindableType jpaBindableType) {
|
Bindable.BindableType jpaBindableType,
|
||||||
return resolveSqmPathSource( name, null, valueDomainType, jpaBindableType, false );
|
boolean isGeneric) {
|
||||||
|
return resolveSqmPathSource( name, null, valueDomainType, jpaBindableType, isGeneric );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <J> SqmPathSource<J> resolveSqmPathSource(
|
public static <J> SqmPathSource<J> resolveSqmPathSource(
|
||||||
|
@ -93,7 +96,8 @@ public class SqmMappingModelHelper {
|
||||||
name,
|
name,
|
||||||
pathModel,
|
pathModel,
|
||||||
(BasicDomainType<J>) valueDomainType,
|
(BasicDomainType<J>) valueDomainType,
|
||||||
jpaBindableType
|
jpaBindableType,
|
||||||
|
isGeneric
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +125,8 @@ public class SqmMappingModelHelper {
|
||||||
name,
|
name,
|
||||||
pathModel,
|
pathModel,
|
||||||
(EntityDomainType<J>) valueDomainType,
|
(EntityDomainType<J>) valueDomainType,
|
||||||
jpaBindableType
|
jpaBindableType,
|
||||||
|
isGeneric
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,9 @@ import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
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.EntityDomainType;
|
||||||
|
import org.hibernate.metamodel.model.domain.ManagedDomainType;
|
||||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||||
import org.hibernate.query.sqm.NodeBuilder;
|
import org.hibernate.query.sqm.NodeBuilder;
|
||||||
import org.hibernate.query.sqm.SqmExpressible;
|
import org.hibernate.query.sqm.SqmExpressible;
|
||||||
|
@ -140,6 +142,17 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPathSource<?> getResolvedModel() {
|
public SqmPathSource<?> getResolvedModel() {
|
||||||
|
final DomainType<?> lhsType;
|
||||||
|
final SqmPathSource<T> 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();
|
return getModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,9 +176,7 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public SqmPath<?> get(String attributeName) {
|
public SqmPath<?> get(String attributeName) {
|
||||||
|
final SqmPathSource<?> subNavigable = getResolvedModel().getSubPathSource( attributeName );
|
||||||
final SqmPathSource<?> subNavigable = getReferencedPathSource().getSubPathSource( attributeName );
|
|
||||||
|
|
||||||
return resolvePath( attributeName, subNavigable );
|
return resolvePath( attributeName, subNavigable );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,11 @@ public class SqmCteRoot<T> extends SqmRoot<T> implements JpaRoot<T> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPathSource<?> getResolvedModel() {
|
||||||
|
return getReferencedPathSource();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmCorrelatedRoot<T> createCorrelation() {
|
public SqmCorrelatedRoot<T> createCorrelation() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
|
|
@ -92,6 +92,11 @@ public class SqmDerivedRoot<T> extends SqmRoot<T> implements JpaDerivedRoot<T> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmPathSource<?> getResolvedModel() {
|
||||||
|
return getReferencedPathSource();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmCorrelatedRoot<T> createCorrelation() {
|
public SqmCorrelatedRoot<T> createCorrelation() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
|
|
@ -6,12 +6,8 @@
|
||||||
*/
|
*/
|
||||||
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.query.PathException;
|
import org.hibernate.query.PathException;
|
||||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||||
import org.hibernate.query.sqm.NodeBuilder;
|
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.SqmExpressible;
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
import org.hibernate.query.sqm.SqmPathSource;
|
||||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||||
|
import org.hibernate.spi.NavigablePath;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,29 +77,6 @@ public class SqmEmbeddedValuedSimplePath<T>
|
||||||
return sqmPath;
|
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<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 ) {
|
|
||||||
return concreteEmbeddable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return getModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <X> X accept(SemanticQueryWalker<X> walker) {
|
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||||
return walker.visitEmbeddableValuedPath( this );
|
return walker.visitEmbeddableValuedPath( this );
|
||||||
|
|
|
@ -210,7 +210,7 @@ public class SqmPolymorphicRootDescriptor<T> implements EntityDomainType<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SingularPersistentAttribute<? super T, ?> findConcreteEmbeddableAttribute(String name) {
|
public PersistentAttribute<? super T, ?> findConcreteGenericAttribute(String name) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ public class SqmPolymorphicRootDescriptor<T> implements EntityDomainType<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SingularPersistentAttribute<? super T, ?> findDeclaredConcreteEmbeddableAttribute(String name) {
|
public PersistentAttribute<? super T, ?> findDeclaredConcreteGenericAttribute(String name) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue