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) { public static <Y> DomainType<Y> determineSimpleType(ValueContext typeContext, MetadataContext context) {
switch ( typeContext.getValueClassification() ) { switch ( typeContext.getValueClassification() ) {
case BASIC: { case BASIC: {
Class returnedClass = typeContext.getJpaBindableType(); final Class<?> jpaBindableType = typeContext.getJpaBindableType();
if ( returnedClass.isAssignableFrom( Object.class ) ) { if ( jpaBindableType.isPrimitive() ) {
final SimpleValue simpleValue = (SimpleValue) typeContext.getHibernateValue(); // Special BasicDomainType necessary for primitive types in the JPA metamodel
if ( simpleValue.getTypeParameters() != null && typeContext.getAttributeMetadata() return (DomainType<Y>) context.resolveBasicType( jpaBindableType );
.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 ); return (DomainType<Y>) typeContext.getHibernateValue().getType();
} }
case ENTITY: { case ENTITY: {
final org.hibernate.type.Type type = typeContext.getHibernateValue().getType(); 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) { public static ParameterizedType getSignatureType(Member member) {
final java.lang.reflect.Type type; final java.lang.reflect.Type type;
if ( member instanceof Field ) { if ( member instanceof Field ) {

View File

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

View File

@ -51,8 +51,24 @@ public class BindingTypeHelper {
final TemporalJavaType<T> temporalJtd = (TemporalJavaType<T>) sqmExpressible.getExpressibleJavaType(); final TemporalJavaType<T> temporalJtd = (TemporalJavaType<T>) sqmExpressible.getExpressibleJavaType();
if ( temporalJtd.getPrecision() != precision ) { if ( temporalJtd.getPrecision() != precision ) {
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration(); 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( return typeConfiguration.getBasicTypeRegistry().resolve(
temporalJtd.resolveTypeForPrecision( precision, typeConfiguration ), temporalTypeForPrecision,
TemporalJavaType.resolveJdbcTypeCode( precision ) TemporalJavaType.resolveJdbcTypeCode( precision )
); );
} }

View File

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

View File

@ -1037,7 +1037,7 @@ public class QueryTest extends BaseEntityManagerFunctionalTestCase {
try { try {
Query query = em.createQuery( "select w from " + Wallet.class.getName() + " w where w.marketEntrance = :me" ); Query query = em.createQuery( "select w from " + Wallet.class.getName() + " w where w.marketEntrance = :me" );
Parameter parameter = query.getParameter( "me", Date.class ); 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() );
query.setParameter( "me", new Date(), TemporalType.DATE ); query.setParameter( "me", new Date(), TemporalType.DATE );