HHH-16749 Reuse BasicType from Value for JPA Metamodel instead of creating dedicated BasicDomainType instances

This commit is contained in:
Christian Beikov 2023-06-13 11:48:23 +02:00
parent 6ed858a461
commit 97a699a3e1
6 changed files with 38 additions and 56 deletions

View File

@ -235,18 +235,12 @@ public class AttributeFactory {
public static <Y> DomainType<Y> determineSimpleType(ValueContext typeContext, MetadataContext context) {
switch ( typeContext.getValueClassification() ) {
case BASIC: {
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();
final Class<?> jpaBindableType = typeContext.getJpaBindableType();
if ( jpaBindableType.isPrimitive() ) {
// Special BasicDomainType necessary for primitive types in the JPA metamodel
return (DomainType<Y>) context.resolveBasicType( jpaBindableType );
}
}
return context.resolveBasicType( returnedClass );
return (DomainType<Y>) typeContext.getHibernateValue().getType();
}
case ENTITY: {
final org.hibernate.type.Type type = typeContext.getHibernateValue().getType();
@ -555,45 +549,6 @@ public class AttributeFactory {
}
}
protected <Y> Class<Y> accountForPrimitiveTypes(Class<Y> declaredType) {
return accountForPrimitiveTypes( declaredType, context );
}
public static <Y> Class<Y> accountForPrimitiveTypes(Class<Y> declaredType, MetadataContext metadataContext) {
// if ( !declaredType.isPrimitive() ) {
// return declaredType;
// }
//
// if ( Boolean.TYPE.equals( declaredType ) ) {
// return (Class<Y>) Boolean.class;
// }
// if ( Character.TYPE.equals( declaredType ) ) {
// return (Class<Y>) Character.class;
// }
// if( Byte.TYPE.equals( declaredType ) ) {
// return (Class<Y>) Byte.class;
// }
// if ( Short.TYPE.equals( declaredType ) ) {
// return (Class<Y>) Short.class;
// }
// if ( Integer.TYPE.equals( declaredType ) ) {
// return (Class<Y>) Integer.class;
// }
// if ( Long.TYPE.equals( declaredType ) ) {
// return (Class<Y>) Long.class;
// }
// if ( Float.TYPE.equals( declaredType ) ) {
// return (Class<Y>) Float.class;
// }
// if ( Double.TYPE.equals( declaredType ) ) {
// return (Class<Y>) Double.class;
// }
//
// throw new IllegalArgumentException( "Unexpected type [" + declaredType + "]" );
// if the field is defined as int, return int not Integer...
return declaredType;
}
public static ParameterizedType getSignatureType(Member member) {
final java.lang.reflect.Type type;
if ( member instanceof Field ) {

View File

@ -54,8 +54,7 @@ public abstract class BaseAttributeMetadata<X, Y> implements AttributeMetadata<X
else {
throw new IllegalArgumentException( "Cannot determine java-type from given member [" + member + "]" );
}
//noinspection unchecked
this.javaType = AttributeFactory.accountForPrimitiveTypes( declaredType, metadataContext );
this.javaType = declaredType;
}
public String getName() {

View File

@ -51,8 +51,24 @@ public class BindingTypeHelper {
final TemporalJavaType<T> temporalJtd = (TemporalJavaType<T>) sqmExpressible.getExpressibleJavaType();
if ( temporalJtd.getPrecision() != precision ) {
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
final TemporalJavaType<T> temporalTypeForPrecision;
// Special case java.util.Date, because TemporalJavaType#resolveTypeForPrecision doesn't support widening,
// since the main purpose of that method is to determine the final java type based on the reflective type
// + the explicit @Temporal(TemporalType...) configuration
if ( java.util.Date.class.isAssignableFrom( temporalJtd.getJavaTypeClass() ) ) {
//noinspection unchecked
temporalTypeForPrecision = (TemporalJavaType<T>) typeConfiguration.getJavaTypeRegistry().getDescriptor(
TemporalJavaType.resolveJavaTypeClass( precision )
);
}
else {
temporalTypeForPrecision = temporalJtd.resolveTypeForPrecision(
precision,
typeConfiguration
);
}
return typeConfiguration.getBasicTypeRegistry().resolve(
temporalJtd.resolveTypeForPrecision( precision, typeConfiguration ),
temporalTypeForPrecision,
TemporalJavaType.resolveJdbcTypeCode( precision )
);
}

View File

@ -637,7 +637,7 @@ public abstract class AbstractCommonQueryContract implements CommonQueryContract
try {
//noinspection rawtypes
final QueryParameterImplementor parameter = getParameterMetadata().getQueryParameter( name );
if ( !parameter.getParameterType().isAssignableFrom( type ) ) {
if ( !type.isAssignableFrom( parameter.getParameterType() ) ) {
throw new IllegalArgumentException(
"The type [" + parameter.getParameterType().getName() +
"] associated with the parameter corresponding to name [" + name +
@ -668,7 +668,7 @@ public abstract class AbstractCommonQueryContract implements CommonQueryContract
try {
final QueryParameterImplementor parameter = getParameterMetadata().getQueryParameter( position );
if ( !parameter.getParameterType().isAssignableFrom( type ) ) {
if ( !type.isAssignableFrom( parameter.getParameterType() ) ) {
throw new IllegalArgumentException(
"The type [" + parameter.getParameterType().getName() +
"] associated with the parameter corresponding to position [" + position +

View File

@ -33,6 +33,18 @@ public interface TemporalJavaType<T> extends BasicJavaType<T> {
throw new UnsupportedOperationException( "Unsupported precision: " + requestedTemporalPrecision );
}
static Class<?> resolveJavaTypeClass(TemporalType requestedTemporalPrecision) {
switch ( requestedTemporalPrecision ) {
case DATE:
return java.sql.Date.class;
case TIME:
return java.sql.Time.class;
case TIMESTAMP:
return java.sql.Timestamp.class;
}
throw new UnsupportedOperationException( "Unsupported precision: " + requestedTemporalPrecision );
}
/**
* The precision represented by this type
*/

View File

@ -1037,7 +1037,7 @@ public class QueryTest extends BaseEntityManagerFunctionalTestCase {
try {
Query query = em.createQuery( "select w from " + Wallet.class.getName() + " w where w.marketEntrance = :me" );
Parameter parameter = query.getParameter( "me", Date.class );
assertEquals( parameter.getParameterType(), Date.class );
assertEquals( parameter.getParameterType(), java.sql.Timestamp.class );
query.setParameter( "me", new Date() );
query.setParameter( "me", new Date(), TemporalType.DATE );