HHH-16241 Add relational java type to SqmExpressible for function argument validation

This commit is contained in:
Marco Belladelli 2023-03-09 10:36:44 +01:00 committed by Christian Beikov
parent 0119236d8d
commit ca6c44937e
8 changed files with 57 additions and 5 deletions

View File

@ -13,6 +13,7 @@ import java.lang.reflect.ParameterizedType;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.PropertyNotFoundException; import org.hibernate.PropertyNotFoundException;
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
import org.hibernate.internal.EntityManagerMessageLogger; import org.hibernate.internal.EntityManagerMessageLogger;
import org.hibernate.internal.HEMLogging; import org.hibernate.internal.HEMLogging;
import org.hibernate.mapping.Any; import org.hibernate.mapping.Any;
@ -28,6 +29,7 @@ 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;
import org.hibernate.metamodel.UnsupportedMappingException; import org.hibernate.metamodel.UnsupportedMappingException;
import org.hibernate.metamodel.ValueClassification;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping; import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.EmbeddableMappingType;
@ -125,13 +127,19 @@ public class AttributeFactory {
); );
} }
final SingularAttributeMetadata<X, Y> singularAttributeMetadata = (SingularAttributeMetadata<X, Y>) attributeMetadata; final ValueContext valueContext = ( (SingularAttributeMetadata<X, Y>) attributeMetadata ).getValueContext();
final DomainType<Y> metaModelType = determineSimpleType( singularAttributeMetadata.getValueContext(), metadataContext ); final DomainType<Y> metaModelType = determineSimpleType( valueContext, metadataContext );
final JavaType<?> relationalJavaType = determineRelationalJavaType(
valueContext,
metaModelType,
metadataContext
);
return new SingularAttributeImpl<>( return new SingularAttributeImpl<>(
ownerType, ownerType,
attributeMetadata.getName(), attributeMetadata.getName(),
attributeMetadata.getAttributeClassification(), attributeMetadata.getAttributeClassification(),
metaModelType, metaModelType,
relationalJavaType,
attributeMetadata.getMember(), attributeMetadata.getMember(),
false, false,
false, false,
@ -329,6 +337,21 @@ public class AttributeFactory {
} }
} }
private static JavaType<?> determineRelationalJavaType(
ValueContext typeContext,
DomainType<?> metaModelType,
MetadataContext context) {
if ( typeContext.getValueClassification() == ValueClassification.BASIC ) {
final ConverterDescriptor descriptor = ( (SimpleValue) typeContext.getHibernateValue() ).getJpaAttributeConverterDescriptor();
if ( descriptor != null ) {
return context.getJavaTypeRegistry().resolveDescriptor(
descriptor.getRelationalValueResolvedType().getErasedType()
);
}
}
return metaModelType.getExpressibleJavaType();
}
private static EntityPersister getDeclaringEntity( private static EntityPersister getDeclaringEntity(
AbstractIdentifiableType<?> ownerType, AbstractIdentifiableType<?> ownerType,
MetadataContext metadataContext) { MetadataContext metadataContext) {

View File

@ -416,6 +416,7 @@ public abstract class AbstractIdentifiableType<J>
EntityIdentifierMapping.ROLE_LOCAL_NAME, EntityIdentifierMapping.ROLE_LOCAL_NAME,
(SqmPathSource) id, (SqmPathSource) id,
(BasicDomainType<?>) type, (BasicDomainType<?>) type,
type.getExpressibleJavaType(),
Bindable.BindableType.SINGULAR_ATTRIBUTE, Bindable.BindableType.SINGULAR_ATTRIBUTE,
id.isGeneric() id.isGeneric()
); );

View File

@ -33,6 +33,7 @@ public class AnyMappingSqmPathSource<J> extends AbstractSqmPathSource<J> {
"id", "id",
null, null,
(BasicDomainType<?>) domainType.getKeyType(), (BasicDomainType<?>) domainType.getKeyType(),
domainType.getKeyType().getExpressibleJavaType(),
SINGULAR_ATTRIBUTE, SINGULAR_ATTRIBUTE,
false false
); );

View File

@ -8,10 +8,11 @@ package org.hibernate.metamodel.model.domain.internal;
import org.hibernate.metamodel.model.domain.BasicDomainType; import org.hibernate.metamodel.model.domain.BasicDomainType;
import org.hibernate.query.ReturnableType; import org.hibernate.query.ReturnableType;
import org.hibernate.spi.NavigablePath;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.spi.NavigablePath;
import org.hibernate.type.descriptor.java.JavaType;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -19,15 +20,18 @@ 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 JavaType<?> relationalJavaType;
private final boolean isGeneric; private final boolean isGeneric;
public BasicSqmPathSource( public BasicSqmPathSource(
String localPathName, String localPathName,
SqmPathSource<J> pathModel, SqmPathSource<J> pathModel,
BasicDomainType<J> domainType, BasicDomainType<J> domainType,
JavaType<?> relationalJavaType,
BindableType jpaBindableType, BindableType jpaBindableType,
boolean isGeneric) { boolean isGeneric) {
super( localPathName, pathModel, domainType, jpaBindableType ); super( localPathName, pathModel, domainType, jpaBindableType );
this.relationalJavaType = relationalJavaType;
this.isGeneric = isGeneric; this.isGeneric = isGeneric;
} }
@ -69,6 +73,11 @@ public class BasicSqmPathSource<J>
return getExpressibleJavaType().getJavaTypeClass(); return getExpressibleJavaType().getJavaTypeClass();
} }
@Override
public JavaType<?> getRelationalJavaType() {
return relationalJavaType;
}
@Override @Override
public boolean isGeneric() { public boolean isGeneric() {
return isGeneric; return isGeneric;

View File

@ -55,6 +55,7 @@ public class SingularAttributeImpl<D,J>
String name, String name,
AttributeClassification attributeClassification, AttributeClassification attributeClassification,
DomainType<J> attributeType, DomainType<J> attributeType,
JavaType<?> relationalJavaType,
Member member, Member member,
boolean isIdentifier, boolean isIdentifier,
boolean isVersion, boolean isVersion,
@ -79,6 +80,7 @@ public class SingularAttributeImpl<D,J>
name, name,
this, this,
attributeType, attributeType,
relationalJavaType,
BindableType.SINGULAR_ATTRIBUTE, BindableType.SINGULAR_ATTRIBUTE,
isGeneric isGeneric
); );
@ -174,6 +176,7 @@ public class SingularAttributeImpl<D,J>
name, name,
attributeClassification, attributeClassification,
attributeType, attributeType,
attributeType.getExpressibleJavaType(),
member, member,
true, true,
false, false,
@ -215,6 +218,7 @@ public class SingularAttributeImpl<D,J>
name, name,
attributeClassification, attributeClassification,
attributeType, attributeType,
attributeType.getExpressibleJavaType(),
member, member,
false, false,
true, true,

View File

@ -25,6 +25,10 @@ public interface SqmExpressible<J> extends BindableType<J> {
*/ */
JavaType<J> getExpressibleJavaType(); JavaType<J> getExpressibleJavaType();
default JavaType<?> getRelationalJavaType() {
return getExpressibleJavaType();
}
@Override @Override
default boolean isInstance(J value) { default boolean isInstance(J value) {
return getExpressibleJavaType().isInstance( value ); return getExpressibleJavaType().isInstance( value );

View File

@ -38,6 +38,7 @@ import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.JavaType;
import jakarta.persistence.metamodel.Bindable; import jakarta.persistence.metamodel.Bindable;
@ -81,13 +82,21 @@ public class SqmMappingModelHelper {
DomainType<J> valueDomainType, DomainType<J> valueDomainType,
Bindable.BindableType jpaBindableType, Bindable.BindableType jpaBindableType,
boolean isGeneric) { boolean isGeneric) {
return resolveSqmPathSource( name, null, valueDomainType, jpaBindableType, isGeneric ); return resolveSqmPathSource(
name,
null,
valueDomainType,
valueDomainType.getExpressibleJavaType(),
jpaBindableType,
isGeneric
);
} }
public static <J> SqmPathSource<J> resolveSqmPathSource( public static <J> SqmPathSource<J> resolveSqmPathSource(
String name, String name,
SqmPathSource<J> pathModel, SqmPathSource<J> pathModel,
DomainType<J> valueDomainType, DomainType<J> valueDomainType,
JavaType<?> relationalJavaType,
Bindable.BindableType jpaBindableType, Bindable.BindableType jpaBindableType,
boolean isGeneric) { boolean isGeneric) {
@ -96,6 +105,7 @@ public class SqmMappingModelHelper {
name, name,
pathModel, pathModel,
(BasicDomainType<J>) valueDomainType, (BasicDomainType<J>) valueDomainType,
relationalJavaType,
jpaBindableType, jpaBindableType,
isGeneric isGeneric
); );

View File

@ -91,7 +91,7 @@ public class ArgumentTypesValidator implements ArgumentsValidator {
SqmExpressible<?> nodeType = argument.getNodeType(); SqmExpressible<?> nodeType = argument.getNodeType();
FunctionParameterType type = count < types.length ? types[count++] : types[types.length - 1]; FunctionParameterType type = count < types.length ? types[count++] : types[types.length - 1];
if ( nodeType != null ) { if ( nodeType != null ) {
JavaType<?> javaType = nodeType.getExpressibleJavaType(); JavaType<?> javaType = nodeType.getRelationalJavaType();
if (javaType != null) { if (javaType != null) {
try { try {
checkType( checkType(