Switch from java.lang.Class to java.lang.reflect.Type in the metamodel to support parameterized types

This commit is contained in:
Christian Beikov 2021-03-08 16:22:20 +01:00
parent 4a1a084def
commit 350fd81cf5
27 changed files with 176 additions and 85 deletions

View File

@ -138,7 +138,7 @@ public class InferredBasicValueResolver {
if ( jdbcMapping == null ) { if ( jdbcMapping == null ) {
throw new MappingException( throw new MappingException(
"Could not determine JavaTypeDescriptor nor SqlTypeDescriptor to use" + "" + "Could not determine JavaTypeDescriptor nor SqlTypeDescriptor to use" + "" +
" for " + ( (BasicValue) stdIndicators ).getResolvedJavaClass() + " for " + ( (BasicValue) stdIndicators ).getResolvedJavaType() +
"; table = " + table.getName() + "; table = " + table.getName() +
"; column = " + selectable.getText() "; column = " + selectable.getText()
); );

View File

@ -35,7 +35,7 @@ public class VersionResolution<E> implements BasicValue.Resolution<E> {
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
public static <E> VersionResolution<E> from( public static <E> VersionResolution<E> from(
Function<TypeConfiguration, Class> implicitJavaTypeAccess, Function<TypeConfiguration, java.lang.reflect.Type> implicitJavaTypeAccess,
Function<TypeConfiguration, BasicJavaDescriptor> explicitJtdAccess, Function<TypeConfiguration, BasicJavaDescriptor> explicitJtdAccess,
Function<TypeConfiguration, SqlTypeDescriptor> explicitStdAccess, Function<TypeConfiguration, SqlTypeDescriptor> explicitStdAccess,
TypeConfiguration typeConfiguration, TypeConfiguration typeConfiguration,
@ -43,7 +43,7 @@ public class VersionResolution<E> implements BasicValue.Resolution<E> {
// todo (6.0) : add support for Dialect-specific interpretation? // todo (6.0) : add support for Dialect-specific interpretation?
final Class implicitJavaType = implicitJavaTypeAccess.apply( typeConfiguration ); final java.lang.reflect.Type implicitJavaType = implicitJavaTypeAccess.apply( typeConfiguration );
final JavaTypeDescriptor registered = typeConfiguration.getJavaTypeDescriptorRegistry().resolveDescriptor( implicitJavaType ); final JavaTypeDescriptor registered = typeConfiguration.getJavaTypeDescriptorRegistry().resolveDescriptor( implicitJavaType );
if ( registered instanceof PrimitiveByteArrayTypeDescriptor ) { if ( registered instanceof PrimitiveByteArrayTypeDescriptor ) {

View File

@ -50,6 +50,7 @@ import org.hibernate.cfg.SetBasicValueTypeSecondPass;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.mapping.BasicValue; import org.hibernate.mapping.BasicValue;
import org.hibernate.mapping.Table; import org.hibernate.mapping.Table;
import org.hibernate.type.descriptor.java.BasicJavaDescriptor; import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
@ -98,7 +99,7 @@ public class BasicValueBinder<T> implements SqlTypeDescriptorIndicators {
private Function<TypeConfiguration,SqlTypeDescriptor> explicitSqlTypeAccess; private Function<TypeConfiguration,SqlTypeDescriptor> explicitSqlTypeAccess;
private Function<TypeConfiguration, BasicJavaDescriptor> explicitJtdAccess; private Function<TypeConfiguration, BasicJavaDescriptor> explicitJtdAccess;
private Function<TypeConfiguration, MutabilityPlan> explicitMutabilityAccess; private Function<TypeConfiguration, MutabilityPlan> explicitMutabilityAccess;
private Function<TypeConfiguration, Class> implicitJavaTypeAccess; private Function<TypeConfiguration, java.lang.reflect.Type> implicitJavaTypeAccess;
private AccessType accessType; private AccessType accessType;
@ -595,7 +596,7 @@ public class BasicValueBinder<T> implements SqlTypeDescriptorIndicators {
} }
// see if the value's type Class is annotated `@Immutable` // see if the value's type Class is annotated `@Immutable`
final Class attributeType = implicitJavaTypeAccess.apply( typeConfiguration ); final Class attributeType = ReflectHelper.getClass( implicitJavaTypeAccess.apply( typeConfiguration ) );
if ( attributeType.isAnnotationPresent( Immutable.class ) ) { if ( attributeType.isAnnotationPresent( Immutable.class ) ) {
return ImmutableMutabilityPlan.instance(); return ImmutableMutabilityPlan.instance();
} }

View File

@ -13,6 +13,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.util.Locale; import java.util.Locale;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.persistence.Transient; import javax.persistence.Transient;
@ -214,6 +215,19 @@ public final class ReflectHelper {
String className, String className,
String name, String name,
ClassLoaderService classLoaderService) throws MappingException { ClassLoaderService classLoaderService) throws MappingException {
try {
Class clazz = classLoaderService.classForName( className );
return getter( clazz, name ).getReturnTypeClass();
}
catch ( ClassLoadingException e ) {
throw new MappingException( "class " + className + " not found while looking for property: " + name, e );
}
}
public static java.lang.reflect.Type reflectedPropertyType(
String className,
String name,
ClassLoaderService classLoaderService) throws MappingException {
try { try {
Class clazz = classLoaderService.classForName( className ); Class clazz = classLoaderService.classForName( className );
return getter( clazz, name ).getReturnType(); return getter( clazz, name ).getReturnType();
@ -232,7 +246,7 @@ public final class ReflectHelper {
* @throws MappingException Indicates we were unable to locate the property. * @throws MappingException Indicates we were unable to locate the property.
*/ */
public static Class reflectedPropertyClass(Class clazz, String name) throws MappingException { public static Class reflectedPropertyClass(Class clazz, String name) throws MappingException {
return getter( clazz, name ).getReturnType(); return getter( clazz, name ).getReturnTypeClass();
} }
private static Getter getter(Class clazz, String name) throws MappingException { private static Getter getter(Class clazz, String name) throws MappingException {
@ -723,4 +737,17 @@ public final class ReflectHelper {
return null; return null;
} }
public static <T> Class<T> getClass(java.lang.reflect.Type type) {
if ( type == null ) {
return null;
}
else if ( type instanceof Class<?> ) {
return (Class<T>) type;
}
else if ( type instanceof ParameterizedType ) {
return (Class<T>) ( (ParameterizedType) type ).getRawType();
}
throw new UnsupportedOperationException( "Can't get java type class from type: " + type );
}
} }

View File

@ -62,15 +62,15 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato
private String explicitTypeName; private String explicitTypeName;
private Map explicitLocalTypeParams; private Map explicitLocalTypeParams;
private Function<TypeConfiguration,BasicJavaDescriptor> explicitJavaTypeAccess; private Function<TypeConfiguration, BasicJavaDescriptor> explicitJavaTypeAccess;
private Function<TypeConfiguration,SqlTypeDescriptor> explicitSqlTypeAccess; private Function<TypeConfiguration, SqlTypeDescriptor> explicitSqlTypeAccess;
private Function<TypeConfiguration,MutabilityPlan> explicitMutabilityPlanAccess; private Function<TypeConfiguration, MutabilityPlan> explicitMutabilityPlanAccess;
private Function<TypeConfiguration,Class> implicitJavaTypeAccess; private Function<TypeConfiguration, java.lang.reflect.Type> implicitJavaTypeAccess;
private EnumType enumerationStyle; private EnumType enumerationStyle;
private TemporalType temporalPrecision; private TemporalType temporalPrecision;
private Class resolvedJavaClass; private java.lang.reflect.Type resolvedJavaType;
private String ownerName; private String ownerName;
private String propertyName; private String propertyName;
@ -138,7 +138,7 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato
this.explicitMutabilityPlanAccess = explicitMutabilityPlanAccess; this.explicitMutabilityPlanAccess = explicitMutabilityPlanAccess;
} }
public void setImplicitJavaTypeAccess(Function<TypeConfiguration, Class> implicitJavaTypeAccess) { public void setImplicitJavaTypeAccess(Function<TypeConfiguration, java.lang.reflect.Type> implicitJavaTypeAccess) {
this.implicitJavaTypeAccess = implicitJavaTypeAccess; this.implicitJavaTypeAccess = implicitJavaTypeAccess;
} }
@ -149,8 +149,8 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato
return getColumn( 0 ); return getColumn( 0 );
} }
public Class getResolvedJavaClass() { public java.lang.reflect.Type getResolvedJavaType() {
return resolvedJavaClass; return resolvedJavaType;
} }
@Override @Override
@ -344,7 +344,7 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato
if ( jtd == null ) { if ( jtd == null ) {
if ( implicitJavaTypeAccess != null ) { if ( implicitJavaTypeAccess != null ) {
final Class implicitJtd = implicitJavaTypeAccess.apply( typeConfiguration ); final java.lang.reflect.Type implicitJtd = implicitJavaTypeAccess.apply( typeConfiguration );
if ( implicitJtd != null ) { if ( implicitJtd != null ) {
jtd = typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( implicitJtd ); jtd = typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( implicitJtd );
} }
@ -403,10 +403,10 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato
} }
private JavaTypeDescriptor determineReflectedJavaTypeDescriptor() { private JavaTypeDescriptor determineReflectedJavaTypeDescriptor() {
final Class impliedJavaType; final java.lang.reflect.Type impliedJavaType;
if ( resolvedJavaClass != null ) { if ( resolvedJavaType != null ) {
impliedJavaType = resolvedJavaClass; impliedJavaType = resolvedJavaType;
} }
else if ( implicitJavaTypeAccess != null ) { else if ( implicitJavaTypeAccess != null ) {
impliedJavaType = implicitJavaTypeAccess.apply( typeConfiguration ); impliedJavaType = implicitJavaTypeAccess.apply( typeConfiguration );
@ -415,7 +415,7 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato
final ServiceRegistry serviceRegistry = typeConfiguration.getServiceRegistry(); final ServiceRegistry serviceRegistry = typeConfiguration.getServiceRegistry();
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
impliedJavaType = ReflectHelper.reflectedPropertyClass( impliedJavaType = ReflectHelper.reflectedPropertyType(
ownerName, ownerName,
propertyName, propertyName,
classLoaderService classLoaderService
@ -425,7 +425,7 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato
return null; return null;
} }
resolvedJavaClass = impliedJavaType; resolvedJavaType = impliedJavaType;
return typeConfiguration.getJavaTypeDescriptorRegistry().resolveDescriptor( impliedJavaType ); return typeConfiguration.getJavaTypeDescriptorRegistry().resolveDescriptor( impliedJavaType );
} }
@ -434,7 +434,7 @@ public class BasicValue extends SimpleValue implements SqlTypeDescriptorIndicato
private static Resolution interpretExplicitlyNamedType( private static Resolution interpretExplicitlyNamedType(
String name, String name,
EnumType enumerationStyle, EnumType enumerationStyle,
Function<TypeConfiguration, Class> implicitJavaTypeAccess, Function<TypeConfiguration, java.lang.reflect.Type> implicitJavaTypeAccess,
Function<TypeConfiguration, BasicJavaDescriptor> explicitJtdAccess, Function<TypeConfiguration, BasicJavaDescriptor> explicitJtdAccess,
Function<TypeConfiguration, SqlTypeDescriptor> explicitStdAccess, Function<TypeConfiguration, SqlTypeDescriptor> explicitStdAccess,
Function<TypeConfiguration, MutabilityPlan> explicitMutabilityPlanAccess, Function<TypeConfiguration, MutabilityPlan> explicitMutabilityPlanAccess,

View File

@ -90,7 +90,7 @@ public class Property implements Serializable, MetaAttributable {
} }
public boolean isPrimitive(Class clazz) { public boolean isPrimitive(Class clazz) {
return getGetter(clazz).getReturnType().isPrimitive(); return getGetter(clazz).getReturnTypeClass().isPrimitive();
} }
public CascadeStyle getCascadeStyle() throws MappingException { public CascadeStyle getCascadeStyle() throws MappingException {

View File

@ -159,7 +159,7 @@ public class StandardPojoEmbeddableRepresentationStrategy extends AbstractEmbedd
getterNames[i] = propertyAccess.getGetter().getMethodName(); getterNames[i] = propertyAccess.getGetter().getMethodName();
setterNames[i] = propertyAccess.getSetter().getMethodName(); setterNames[i] = propertyAccess.getSetter().getMethodName();
propTypes[i] = propertyAccess.getGetter().getReturnType(); propTypes[i] = propertyAccess.getGetter().getReturnTypeClass();
} }
return Environment.getBytecodeProvider().getReflectionOptimizer( return Environment.getBytecodeProvider().getReflectionOptimizer(

View File

@ -288,7 +288,7 @@ public class StandardPojoEntityRepresentationStrategy implements EntityRepresent
} }
getterNames.add( propertyAccess.getGetter().getMethodName() ); getterNames.add( propertyAccess.getGetter().getMethodName() );
getterTypes.add( propertyAccess.getGetter().getReturnType() ); getterTypes.add( propertyAccess.getGetter().getReturnTypeClass() );
setterNames.add( propertyAccess.getSetter().getMethodName() ); setterNames.add( propertyAccess.getSetter().getMethodName() );

View File

@ -8,6 +8,7 @@ package org.hibernate.property.access.internal;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map; import java.util.Map;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -21,7 +22,7 @@ import org.hibernate.property.access.spi.Setter;
* PropertyAccess for handling non-aggregated composites. * PropertyAccess for handling non-aggregated composites.
* <p/> * <p/>
* IMPL NOTE : We actually use a singleton for the Setter; we cannot for the getter mainly * IMPL NOTE : We actually use a singleton for the Setter; we cannot for the getter mainly
* because we need to differentiate {@link Getter#getReturnType()}. Ultimately I'd prefer to * because we need to differentiate {@link Getter#getReturnTypeClass()}. Ultimately I'd prefer to
* model that "common information" on PropertyAccess itself. * model that "common information" on PropertyAccess itself.
* *
* @author Gavin King * @author Gavin King
@ -73,7 +74,12 @@ public class PropertyAccessEmbeddedImpl implements PropertyAccess {
} }
@Override @Override
public Class getReturnType() { public Class<?> getReturnTypeClass() {
return containerType;
}
@Override
public Type getReturnType() {
return containerType; return containerType;
} }

View File

@ -8,6 +8,7 @@ package org.hibernate.property.access.internal;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map; import java.util.Map;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -68,11 +69,16 @@ public class PropertyAccessMapImpl implements PropertyAccess {
} }
@Override @Override
public Class getReturnType() { public Class<?> getReturnTypeClass() {
// we just don't know... // we just don't know...
return Object.class; return Object.class;
} }
@Override
public Type getReturnType() {
return Object.class;
}
@Override @Override
public Member getMember() { public Member getMember() {
return null; return null;

View File

@ -9,6 +9,7 @@ package org.hibernate.property.access.internal;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map; import java.util.Map;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -102,7 +103,12 @@ public class PropertyAccessStrategyBackRefImpl implements PropertyAccessStrategy
} }
@Override @Override
public Class getReturnType() { public Class<?> getReturnTypeClass() {
return Object.class;
}
@Override
public Type getReturnType() {
return Object.class; return Object.class;
} }

View File

@ -8,6 +8,7 @@ package org.hibernate.property.access.internal;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map; import java.util.Map;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -85,7 +86,12 @@ public class PropertyAccessStrategyIndexBackRefImpl implements PropertyAccessStr
} }
@Override @Override
public Class getReturnType() { public Class<?> getReturnTypeClass() {
return Object.class;
}
@Override
public Type getReturnType() {
return Object.class; return Object.class;
} }

View File

@ -8,6 +8,7 @@ package org.hibernate.property.access.internal;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map; import java.util.Map;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -74,7 +75,12 @@ public class PropertyAccessStrategyNoopImpl implements PropertyAccessStrategy {
} }
@Override @Override
public Class getReturnType() { public Class<?> getReturnTypeClass() {
return Object.class;
}
@Override
public Type getReturnType() {
return Object.class; return Object.class;
} }

View File

@ -11,6 +11,7 @@ import java.io.Serializable;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map; import java.util.Map;
import org.hibernate.PropertyAccessException; import org.hibernate.PropertyAccessException;
@ -102,10 +103,15 @@ public class EnhancedGetterMethodImpl implements Getter {
} }
@Override @Override
public Class getReturnType() { public Class<?> getReturnTypeClass() {
return getterMethod.getReturnType(); return getterMethod.getReturnType();
} }
@Override
public Type getReturnType() {
return getterMethod.getGenericReturnType();
}
@Override @Override
public Member getMember() { public Member getMember() {
return getterMethod; return getterMethod;

View File

@ -9,6 +9,7 @@ package org.hibernate.property.access.spi;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map; import java.util.Map;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
@ -44,12 +45,19 @@ public interface Getter extends Serializable {
*/ */
Object getForInsert(Object owner, Map mergeMap, SharedSessionContractImplementor session); Object getForInsert(Object owner, Map mergeMap, SharedSessionContractImplementor session);
/**
* Retrieve the declared Java type class
*
* @return The declared java type class.
*/
Class<?> getReturnTypeClass();
/** /**
* Retrieve the declared Java type * Retrieve the declared Java type
* *
* @return The declared java type. * @return The declared java type.
*/ */
Class getReturnType(); Type getReturnType();
/** /**
* Retrieve the member to which this property maps. This might be the * Retrieve the member to which this property maps. This might be the

View File

@ -11,6 +11,7 @@ import java.io.Serializable;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@ -91,10 +92,15 @@ public class GetterFieldImpl implements Getter {
} }
@Override @Override
public Class getReturnType() { public Class<?> getReturnTypeClass() {
return field.getType(); return field.getType();
} }
@Override
public Type getReturnType() {
return field.getGenericType();
}
@Override @Override
public Member getMember() { public Member getMember() {
return field; return field;

View File

@ -11,6 +11,7 @@ import java.io.Serializable;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map; import java.util.Map;
import org.hibernate.PropertyAccessException; import org.hibernate.PropertyAccessException;
@ -79,10 +80,15 @@ public class GetterMethodImpl implements Getter {
} }
@Override @Override
public Class getReturnType() { public Class<?> getReturnTypeClass() {
return getterMethod.getReturnType(); return getterMethod.getReturnType();
} }
@Override
public Type getReturnType() {
return getterMethod.getGenericReturnType();
}
@Override @Override
public Member getMember() { public Member getMember() {
return getterMethod; return getterMethod;

View File

@ -764,7 +764,7 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
parameterName parameterName
); );
final Getter getter = propertyAccess.getGetter(); final Getter getter = propertyAccess.getGetter();
final Class retType = getter.getReturnType(); final Class<?> retType = getter.getReturnTypeClass();
final Object object = getter.get( bean ); final Object object = getter.get( bean );
if ( Collection.class.isAssignableFrom( retType ) ) { if ( Collection.class.isAssignableFrom( retType ) ) {
setParameterList( parameterName, (Collection) object ); setParameterList( parameterName, (Collection) object );

View File

@ -1287,7 +1287,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
paramName paramName
); );
final Getter getter = propertyAccess.getGetter(); final Getter getter = propertyAccess.getGetter();
final Class<?> retType = getter.getReturnType(); final Class<?> retType = getter.getReturnTypeClass();
final Object object = getter.get( bean ); final Object object = getter.get( bean );
if ( Collection.class.isAssignableFrom( retType ) ) { if ( Collection.class.isAssignableFrom( retType ) ) {
setParameterList( paramName, (Collection<?>) object ); setParameterList( paramName, (Collection<?>) object );

View File

@ -7,6 +7,7 @@
package org.hibernate.sql.results.graph.instantiation.internal; package org.hibernate.sql.results.graph.instantiation.internal;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -143,7 +144,8 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
// find a constructor matching argument types // find a constructor matching argument types
constructor_loop: constructor_loop:
for ( Constructor<?> constructor : javaTypeDescriptor.getJavaTypeClass().getDeclaredConstructors() ) { for ( Constructor<?> constructor : javaTypeDescriptor.getJavaTypeClass().getDeclaredConstructors() ) {
if ( constructor.getParameterTypes().length != argumentReaders.size() ) { final Type[] genericParameterTypes = constructor.getGenericParameterTypes();
if ( genericParameterTypes.length != argumentReaders.size() ) {
continue; continue;
} }
@ -153,7 +155,7 @@ public class DynamicInstantiationResultImpl<R> implements DynamicInstantiationRe
.getDomainModel() .getDomainModel()
.getTypeConfiguration() .getTypeConfiguration()
.getJavaTypeDescriptorRegistry() .getJavaTypeDescriptorRegistry()
.resolveDescriptor( constructor.getParameterTypes()[i] ); .resolveDescriptor( genericParameterTypes[i] );
final boolean assignmentCompatible = Compatibility.areAssignmentCompatible( final boolean assignmentCompatible = Compatibility.areAssignmentCompatible(
argumentTypeDescriptor, argumentTypeDescriptor,

View File

@ -49,7 +49,7 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer {
for ( int i = 0; i < propertySpan; i++ ) { for ( int i = 0; i < propertySpan; i++ ) {
getterNames[i] = getters[i].getMethodName(); getterNames[i] = getters[i].getMethodName();
setterNames[i] = setters[i].getMethodName(); setterNames[i] = setters[i].getMethodName();
propTypes[i] = getters[i].getReturnType(); propTypes[i] = getters[i].getReturnTypeClass();
} }
final String parentPropertyName = component.getParentProperty(); final String parentPropertyName = component.getParentProperty();

View File

@ -61,7 +61,7 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
for ( int i = 0; i < propertySpan; i++ ) { for ( int i = 0; i < propertySpan; i++ ) {
getterNames[i] = getters[i].getMethodName(); getterNames[i] = getters[i].getMethodName();
setterNames[i] = setters[i].getMethodName(); setterNames[i] = setters[i].getMethodName();
propTypes[i] = getters[i].getReturnType(); propTypes[i] = getters[i].getReturnTypeClass();
} }
if ( hasCustomAccessors || !Environment.useReflectionOptimizer() ) { if ( hasCustomAccessors || !Environment.useReflectionOptimizer() ) {

View File

@ -7,13 +7,13 @@
package org.hibernate.type.descriptor.java; package org.hibernate.type.descriptor.java;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Comparator; import java.util.Comparator;
import java.util.Objects; import java.util.Objects;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.jdbc.Size;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.compare.ComparableComparator; import org.hibernate.internal.util.compare.ComparableComparator;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
@ -185,17 +185,7 @@ public interface JavaTypeDescriptor<T> extends Serializable {
* @return The Java type. * @return The Java type.
*/ */
default Class<T> getJavaTypeClass() { default Class<T> getJavaTypeClass() {
final Type type = getJavaType(); return ReflectHelper.getClass( getJavaType() );
if ( type == null ) {
return null;
}
else if ( type instanceof Class<?> ) {
return (Class<T>) type;
}
else if ( type instanceof ParameterizedType ) {
return (Class<T>) ( (ParameterizedType) type ).getRawType();
}
throw new UnsupportedOperationException( "Can't get java type class from type: " + type );
} }
/** /**

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.type.descriptor.java.spi; package org.hibernate.type.descriptor.java.spi;
import java.lang.reflect.Type;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -72,8 +73,8 @@ import org.hibernate.type.descriptor.java.ZonedDateTimeJavaDescriptor;
*/ */
public class JavaTypeDescriptorBaseline { public class JavaTypeDescriptorBaseline {
public interface BaselineTarget { public interface BaselineTarget {
void addBaselineDescriptor(JavaTypeDescriptor descriptor); void addBaselineDescriptor(JavaTypeDescriptor<?> descriptor);
void addBaselineDescriptor(Class describedJavaType, JavaTypeDescriptor descriptor); void addBaselineDescriptor(Type describedJavaType, JavaTypeDescriptor<?> descriptor);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -7,9 +7,12 @@
package org.hibernate.type.descriptor.java.spi; package org.hibernate.type.descriptor.java.spi;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.hibernate.type.descriptor.java.AbstractClassTypeDescriptor;
import org.hibernate.type.descriptor.java.EnumJavaTypeDescriptor; import org.hibernate.type.descriptor.java.EnumJavaTypeDescriptor;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.java.SerializableTypeDescriptor; import org.hibernate.type.descriptor.java.SerializableTypeDescriptor;
@ -30,7 +33,7 @@ public class JavaTypeDescriptorRegistry implements JavaTypeDescriptorBaseline.Ba
private static final Logger log = Logger.getLogger( JavaTypeDescriptorRegistry.class ); private static final Logger log = Logger.getLogger( JavaTypeDescriptorRegistry.class );
private final TypeConfiguration typeConfiguration; private final TypeConfiguration typeConfiguration;
private ConcurrentHashMap<Class, JavaTypeDescriptor> descriptorsByClass = new ConcurrentHashMap<>(); private final ConcurrentHashMap<Type, JavaTypeDescriptor<?>> descriptorsByType = new ConcurrentHashMap<>();
@SuppressWarnings("unused") @SuppressWarnings("unused")
public JavaTypeDescriptorRegistry(TypeConfiguration typeConfiguration) { public JavaTypeDescriptorRegistry(TypeConfiguration typeConfiguration) {
@ -43,20 +46,20 @@ public class JavaTypeDescriptorRegistry implements JavaTypeDescriptorBaseline.Ba
// baseline descriptors // baseline descriptors
@Override @Override
public void addBaselineDescriptor(JavaTypeDescriptor descriptor) { public void addBaselineDescriptor(JavaTypeDescriptor<?> descriptor) {
if ( descriptor.getJavaType() == null ) { if ( descriptor.getJavaType() == null ) {
throw new IllegalStateException( "Illegal to add BasicJavaTypeDescriptor with null Java type" ); throw new IllegalStateException( "Illegal to add BasicJavaTypeDescriptor with null Java type" );
} }
addBaselineDescriptor( descriptor.getJavaTypeClass(), descriptor ); addBaselineDescriptor( descriptor.getJavaType(), descriptor );
} }
@Override @Override
public void addBaselineDescriptor(Class describedJavaType, JavaTypeDescriptor descriptor) { public void addBaselineDescriptor(Type describedJavaType, JavaTypeDescriptor<?> descriptor) {
performInjections( descriptor ); performInjections( descriptor );
descriptorsByClass.put( describedJavaType, descriptor ); descriptorsByType.put( describedJavaType, descriptor );
} }
private void performInjections(JavaTypeDescriptor descriptor) { private void performInjections(JavaTypeDescriptor<?> descriptor) {
if ( descriptor instanceof TypeConfigurationAware ) { if ( descriptor instanceof TypeConfigurationAware ) {
// would be nice to make the JavaTypeDescriptor for an entity, e.g., aware of the the TypeConfiguration // would be nice to make the JavaTypeDescriptor for an entity, e.g., aware of the the TypeConfiguration
( (TypeConfigurationAware) descriptor ).setTypeConfiguration( typeConfiguration ); ( (TypeConfigurationAware) descriptor ).setTypeConfiguration( typeConfiguration );
@ -67,7 +70,7 @@ public class JavaTypeDescriptorRegistry implements JavaTypeDescriptorBaseline.Ba
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// descriptor access // descriptor access
public <T> JavaTypeDescriptor<T> getDescriptor(Class<T> javaType) { public <T> JavaTypeDescriptor<T> getDescriptor(Type javaType) {
return resolveDescriptor( javaType ); return resolveDescriptor( javaType );
// return RegistryHelper.INSTANCE.resolveDescriptor( // return RegistryHelper.INSTANCE.resolveDescriptor(
// descriptorsByClass, // descriptorsByClass,
@ -98,8 +101,8 @@ public class JavaTypeDescriptorRegistry implements JavaTypeDescriptorBaseline.Ba
// ); // );
} }
public void addDescriptor(JavaTypeDescriptor descriptor) { public void addDescriptor(JavaTypeDescriptor<?> descriptor) {
JavaTypeDescriptor old = descriptorsByClass.put( descriptor.getJavaTypeClass(), descriptor ); JavaTypeDescriptor<?> old = descriptorsByType.put( descriptor.getJavaType(), descriptor );
if ( old != null ) { if ( old != null ) {
log.debugf( log.debugf(
"JavaTypeDescriptorRegistry entry replaced : %s -> %s (was %s)", "JavaTypeDescriptorRegistry entry replaced : %s -> %s (was %s)",
@ -111,34 +114,45 @@ public class JavaTypeDescriptorRegistry implements JavaTypeDescriptorBaseline.Ba
performInjections( descriptor ); performInjections( descriptor );
} }
public <J> JavaTypeDescriptor<J> resolveDescriptor(Class<J> javaType, Supplier<JavaTypeDescriptor<J>> creator) { public <J> JavaTypeDescriptor<J> resolveDescriptor(Type javaType, Supplier<JavaTypeDescriptor<J>> creator) {
final JavaTypeDescriptor cached = descriptorsByClass.get( javaType ); final JavaTypeDescriptor<?> cached = descriptorsByType.get( javaType );
if ( cached != null ) { if ( cached != null ) {
//noinspection unchecked //noinspection unchecked
return cached; return (JavaTypeDescriptor<J>) cached;
} }
final JavaTypeDescriptor<J> created = creator.get(); final JavaTypeDescriptor<J> created = creator.get();
descriptorsByClass.put( javaType, created ); descriptorsByType.put( javaType, created );
return created; return created;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <J> JavaTypeDescriptor<J> resolveDescriptor(Class<J> javaType) { public <J> JavaTypeDescriptor<J> resolveDescriptor(Type javaType) {
return resolveDescriptor( return resolveDescriptor(
javaType, javaType,
() -> { () -> {
// the fallback will always be a basic type // the fallback will always be a basic type
final JavaTypeDescriptor<J> fallbackDescriptor; final AbstractClassTypeDescriptor<J> fallbackDescriptor;
final Class<?> javaTypeClass;
if ( javaType.isEnum() ) { if ( javaType instanceof Class<?> ) {
fallbackDescriptor = new EnumJavaTypeDescriptor( javaType ); javaTypeClass = (Class<?>) javaType;
}
else if ( Serializable.class.isAssignableFrom( javaType ) ) {
fallbackDescriptor = new SerializableTypeDescriptor( javaType );
} }
else { else {
fallbackDescriptor = new JavaTypeDescriptorBasicAdaptor( javaType ); final ParameterizedType parameterizedType = (ParameterizedType) javaType;
javaTypeClass = (Class<?>) parameterizedType.getRawType();
}
if ( javaTypeClass.isEnum() ) {
//noinspection rawtypes
fallbackDescriptor = new EnumJavaTypeDescriptor( javaTypeClass );
}
else if ( Serializable.class.isAssignableFrom( javaTypeClass ) ) {
//noinspection rawtypes
fallbackDescriptor = new SerializableTypeDescriptor( javaTypeClass );
}
else {
//noinspection rawtypes
fallbackDescriptor = new JavaTypeDescriptorBasicAdaptor( javaTypeClass );
} }
// todo (6.0) : here we assume that all temporal type descriptors are registered // todo (6.0) : here we assume that all temporal type descriptors are registered

View File

@ -74,13 +74,13 @@ public class BasicPropertyAccessorTest extends BaseUnitTestCase {
{ {
final PropertyAccess access = accessStrategy.buildPropertyAccess( Duper.class, "it" ); final PropertyAccess access = accessStrategy.buildPropertyAccess( Duper.class, "it" );
assertEquals( String.class, access.getGetter().getReturnType() ); assertEquals( String.class, access.getGetter().getReturnTypeClass() );
assertEquals( Object.class, access.getSetter().getMethod().getParameterTypes()[0] ); assertEquals( Object.class, access.getSetter().getMethod().getParameterTypes()[0] );
} }
{ {
final PropertyAccess access = accessStrategy.buildPropertyAccess( Duper2.class, "it" ); final PropertyAccess access = accessStrategy.buildPropertyAccess( Duper2.class, "it" );
assertEquals( String.class, access.getGetter().getReturnType() ); assertEquals( String.class, access.getGetter().getReturnTypeClass() );
assertEquals( String.class, access.getSetter().getMethod().getParameterTypes()[0] ); assertEquals( String.class, access.getSetter().getMethod().getParameterTypes()[0] );
} }
} }

View File

@ -32,49 +32,49 @@ public class BeanReflectionHelper {
Getter getter = propertyAccess.getGetter(); Getter getter = propertyAccess.getGetter();
Setter setter = propertyAccess.getSetter(); Setter setter = propertyAccess.getSetter();
getterNames[0] = getter.getMethodName(); getterNames[0] = getter.getMethodName();
types[0] = getter.getReturnType(); types[0] = getter.getReturnTypeClass();
setterNames[0] = setter.getMethodName(); setterNames[0] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someLong" ); propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someLong" );
getter = propertyAccess.getGetter(); getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter(); setter = propertyAccess.getSetter();
getterNames[1] = getter.getMethodName(); getterNames[1] = getter.getMethodName();
types[1] = getter.getReturnType(); types[1] = getter.getReturnTypeClass();
setterNames[1] = setter.getMethodName(); setterNames[1] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someInteger" ); propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someInteger" );
getter = propertyAccess.getGetter(); getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter(); setter = propertyAccess.getSetter();
getterNames[2] = getter.getMethodName(); getterNames[2] = getter.getMethodName();
types[2] = getter.getReturnType(); types[2] = getter.getReturnTypeClass();
setterNames[2] = setter.getMethodName(); setterNames[2] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someDate" ); propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someDate" );
getter = propertyAccess.getGetter(); getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter(); setter = propertyAccess.getSetter();
getterNames[3] = getter.getMethodName(); getterNames[3] = getter.getMethodName();
types[3] = getter.getReturnType(); types[3] = getter.getReturnTypeClass();
setterNames[3] = setter.getMethodName(); setterNames[3] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "somelong" ); propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "somelong" );
getter = propertyAccess.getGetter(); getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter(); setter = propertyAccess.getSetter();
getterNames[4] = getter.getMethodName(); getterNames[4] = getter.getMethodName();
types[4] = getter.getReturnType(); types[4] = getter.getReturnTypeClass();
setterNames[4] = setter.getMethodName(); setterNames[4] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someint" ); propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someint" );
getter = propertyAccess.getGetter(); getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter(); setter = propertyAccess.getSetter();
getterNames[5] = getter.getMethodName(); getterNames[5] = getter.getMethodName();
types[5] = getter.getReturnType(); types[5] = getter.getReturnTypeClass();
setterNames[5] = setter.getMethodName(); setterNames[5] = setter.getMethodName();
propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someObject" ); propertyAccess = propertyAccessStrategy.buildPropertyAccess( Bean.class, "someObject" );
getter = propertyAccess.getGetter(); getter = propertyAccess.getGetter();
setter = propertyAccess.getSetter(); setter = propertyAccess.getSetter();
getterNames[6] = getter.getMethodName(); getterNames[6] = getter.getMethodName();
types[6] = getter.getReturnType(); types[6] = getter.getReturnTypeClass();
setterNames[6] = setter.getMethodName(); setterNames[6] = setter.getMethodName();
} }