diff --git a/hibernate-core/src/main/java/org/hibernate/InstantiationException.java b/hibernate-core/src/main/java/org/hibernate/InstantiationException.java index fc63632bf99d..b620c4cc3438 100644 --- a/hibernate-core/src/main/java/org/hibernate/InstantiationException.java +++ b/hibernate-core/src/main/java/org/hibernate/InstantiationException.java @@ -15,7 +15,7 @@ public class InstantiationException extends HibernateException { private final Class clazz; /** - * Constructs a {@code InstantiationException}. + * Constructs an {@code InstantiationException}. * * @param message A message explaining the exception condition * @param clazz The Class we are attempting to instantiate diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/TypeBeanInstanceProducer.java b/hibernate-core/src/main/java/org/hibernate/boot/model/TypeBeanInstanceProducer.java index 20c490290b96..4f8a313b43a6 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/TypeBeanInstanceProducer.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/TypeBeanInstanceProducer.java @@ -6,16 +6,17 @@ */ package org.hibernate.boot.model; -import java.lang.reflect.Constructor; -import java.util.Map; - +import org.hibernate.InstantiationException; import org.hibernate.Internal; -import org.hibernate.MappingException; import org.hibernate.engine.config.spi.ConfigurationService; -import org.hibernate.internal.util.ReflectHelper; import org.hibernate.resource.beans.spi.BeanInstanceProducer; import org.hibernate.type.spi.TypeBootstrapContext; +import java.lang.reflect.Constructor; +import java.util.Map; + +import static org.hibernate.internal.util.ReflectHelper.getConstructor; + /** * {@link BeanInstanceProducer} implementation for building beans related to custom types. * @@ -31,20 +32,29 @@ public TypeBeanInstanceProducer(ConfigurationService configurationService) { @Override public B produceBeanInstance(Class beanType) { - try { - final Constructor bootstrapContextAwareTypeConstructor = ReflectHelper.getConstructor( - beanType, - TypeBootstrapContext.class - ); - if ( bootstrapContextAwareTypeConstructor != null ) { - return bootstrapContextAwareTypeConstructor.newInstance( this ); + final Constructor bootstrapContextAwareConstructor = + getConstructor( beanType, TypeBootstrapContext.class ); + if ( bootstrapContextAwareConstructor != null ) { + try { + return bootstrapContextAwareConstructor.newInstance( this ); } - else { - return beanType.newInstance(); + catch ( Exception e ) { + throw new InstantiationException( "Could not instantiate type", beanType, e ); } } - catch ( Exception e ) { - throw new MappingException( "Could not instantiate Type: " + beanType.getName(), e ); + else { + final Constructor constructor = getConstructor( beanType ); + if ( constructor != null ) { + try { + return constructor.newInstance(); + } + catch ( Exception e ) { + throw new InstantiationException( "Could not instantiate type", beanType, e ); + } + } + else { + throw new InstantiationException( "No appropriate constructor for type", beanType ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/TypeDefinition.java b/hibernate-core/src/main/java/org/hibernate/boot/model/TypeDefinition.java index 9deef365c8ba..eee7e0d9f463 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/TypeDefinition.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/TypeDefinition.java @@ -15,7 +15,6 @@ import java.util.Properties; import java.util.concurrent.atomic.AtomicInteger; -import org.hibernate.boot.model.process.internal.InferredBasicValueResolver; import org.hibernate.boot.model.process.internal.UserTypeResolution; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.spi.BootstrapContext; @@ -42,6 +41,7 @@ import org.hibernate.type.spi.TypeConfigurationAware; import org.hibernate.usertype.UserType; +import static org.hibernate.boot.model.process.internal.InferredBasicValueResolver.resolveSqlTypeIndicators; import static org.hibernate.mapping.MappingHelper.injectParameters; /** @@ -131,9 +131,9 @@ private BasicValue.Resolution createResolution( ); } - private static BasicValue.Resolution createResolution( + private static BasicValue.Resolution createResolution( String name, - Class typeImplementorClass, + Class typeImplementorClass, Map parameters, Map usageSiteProperties, JdbcTypeIndicators indicators, @@ -141,16 +141,18 @@ private static BasicValue.Resolution createResolution( final BootstrapContext bootstrapContext = context.getBootstrapContext(); final TypeConfiguration typeConfiguration = bootstrapContext.getTypeConfiguration(); final BeanInstanceProducer instanceProducer = bootstrapContext.getCustomTypeProducer(); - final boolean isKnownType = Type.class.isAssignableFrom( typeImplementorClass ) + final boolean isKnownType = + Type.class.isAssignableFrom( typeImplementorClass ) || UserType.class.isAssignableFrom( typeImplementorClass ); // support for AttributeConverter would be nice too if ( isKnownType ) { - final Object typeInstance = instantiateType( bootstrapContext.getServiceRegistry(), + final T typeInstance = instantiateType( bootstrapContext.getServiceRegistry(), context.getBuildingOptions(), name, typeImplementorClass, instanceProducer ); if ( typeInstance instanceof TypeConfigurationAware ) { - ( (TypeConfigurationAware) typeInstance ).setTypeConfiguration( typeConfiguration ); + final TypeConfigurationAware configurationAware = (TypeConfigurationAware) typeInstance; + configurationAware.setTypeConfiguration( typeConfiguration ); } final Properties combinedTypeParameters = new Properties(); @@ -164,22 +166,23 @@ private static BasicValue.Resolution createResolution( injectParameters( typeInstance, combinedTypeParameters ); if ( typeInstance instanceof UserType ) { - final UserType userType = (UserType) typeInstance; - final CustomType customType = new CustomType<>( userType, typeConfiguration ); - - return new UserTypeResolution( customType, null, combinedTypeParameters ); + @SuppressWarnings("unchecked") + final UserType userType = (UserType) typeInstance; + final CustomType customType = new CustomType<>( userType, typeConfiguration ); + return new UserTypeResolution<>( customType, null, combinedTypeParameters ); } if ( typeInstance instanceof BasicType ) { - final BasicType resolvedBasicType = (BasicType) typeInstance; + @SuppressWarnings("unchecked") + final BasicType resolvedBasicType = (BasicType) typeInstance; return new BasicValue.Resolution<>() { @Override public JdbcMapping getJdbcMapping() { return resolvedBasicType; } - @Override @SuppressWarnings({"rawtypes", "unchecked"}) - public BasicType getLegacyResolvedBasicType() { + @Override + public BasicType getLegacyResolvedBasicType() { return resolvedBasicType; } @@ -188,8 +191,8 @@ public Properties getCombinedTypeParameters() { return combinedTypeParameters; } - @Override @SuppressWarnings({"rawtypes", "unchecked"}) - public JavaType getDomainJavaType() { + @Override + public JavaType getDomainJavaType() { return resolvedBasicType.getMappedJavaType(); } @@ -204,12 +207,12 @@ public JdbcType getJdbcType() { } @Override - public BasicValueConverter getValueConverter() { + public BasicValueConverter getValueConverter() { return resolvedBasicType.getValueConverter(); } - @Override @SuppressWarnings({"rawtypes", "unchecked"}) - public MutabilityPlan getMutabilityPlan() { + @Override + public MutabilityPlan getMutabilityPlan() { // a TypeDefinition does not explicitly provide a MutabilityPlan (yet?) return resolvedBasicType.isMutable() ? getDomainJavaType().getMutabilityPlan() @@ -220,37 +223,35 @@ public MutabilityPlan getMutabilityPlan() { } // Series of backward compatible special cases + return resolveLegacyCases( typeImplementorClass, indicators, typeConfiguration ); + } + private static BasicValue.Resolution resolveLegacyCases( + Class typeImplementorClass, JdbcTypeIndicators indicators, TypeConfiguration typeConfiguration) { + final BasicType legacyType; if ( Serializable.class.isAssignableFrom( typeImplementorClass ) ) { - @SuppressWarnings({"rawtypes", "unchecked"}) - final SerializableType legacyType = new SerializableType( typeImplementorClass ); - return createBasicTypeResolution( legacyType, typeImplementorClass, indicators, typeConfiguration ); + legacyType = new SerializableType( typeImplementorClass ); } - - if ( typeImplementorClass.isInterface() ) { - return createBasicTypeResolution( new JavaObjectType(), typeImplementorClass, indicators, typeConfiguration ); + else if ( typeImplementorClass.isInterface() ) { + legacyType = (BasicType) new JavaObjectType(); + } + else { + throw new IllegalArgumentException( "Named type [" + typeImplementorClass + + "] did not implement BasicType nor UserType" ); } - throw new IllegalArgumentException( - "Named type [" + typeImplementorClass + "] did not implement BasicType nor UserType" - ); + return createBasicTypeResolution( legacyType, typeImplementorClass, indicators, typeConfiguration ); } - private static BasicValue.Resolution createBasicTypeResolution( - BasicType type, - Class typeImplementorClass, + private static BasicValue.Resolution createBasicTypeResolution( + BasicType type, + Class typeImplementorClass, JdbcTypeIndicators indicators, - TypeConfiguration typeConfiguration - ) { - final JavaType jtd = typeConfiguration - .getJavaTypeRegistry() - .resolveDescriptor( typeImplementorClass ); + TypeConfiguration typeConfiguration) { + final JavaType jtd = typeConfiguration.getJavaTypeRegistry().resolveDescriptor( typeImplementorClass ); final JdbcType jdbcType = typeConfiguration.getJdbcTypeRegistry().getDescriptor( Types.VARBINARY ); - final BasicType resolved = InferredBasicValueResolver.resolveSqlTypeIndicators( - indicators, - typeConfiguration.getBasicTypeRegistry().resolve( jtd, jdbcType ), - jtd - ); + final BasicType basicType = typeConfiguration.getBasicTypeRegistry().resolve( jtd, jdbcType ); + final BasicType resolved = resolveSqlTypeIndicators( indicators, basicType, jtd ); return new BasicValue.Resolution<>() { @Override @@ -259,14 +260,12 @@ public JdbcMapping getJdbcMapping() { } @Override - @SuppressWarnings({ "rawtypes", "unchecked" }) - public BasicType getLegacyResolvedBasicType() { + public BasicType getLegacyResolvedBasicType() { return type; } @Override - @SuppressWarnings({ "rawtypes", "unchecked" }) - public JavaType getDomainJavaType() { + public JavaType getDomainJavaType() { return resolved.getMappedJavaType(); } @@ -281,13 +280,12 @@ public JdbcType getJdbcType() { } @Override - public BasicValueConverter getValueConverter() { + public BasicValueConverter getValueConverter() { return resolved.getValueConverter(); } @Override - @SuppressWarnings({ "rawtypes", "unchecked" }) - public MutabilityPlan getMutabilityPlan() { + public MutabilityPlan getMutabilityPlan() { // a TypeDefinition does not explicitly provide a MutabilityPlan (yet?) return resolved.isMutable() ? getDomainJavaType().getMutabilityPlan() @@ -296,11 +294,11 @@ public MutabilityPlan getMutabilityPlan() { }; } - private static Object instantiateType( + private static T instantiateType( StandardServiceRegistry serviceRegistry, MetadataBuildingOptions buildingOptions, String name, - Class typeImplementorClass, + Class typeImplementorClass, BeanInstanceProducer instanceProducer) { if ( buildingOptions.disallowExtensionsInCdi() ) { return name != null @@ -308,8 +306,8 @@ private static Object instantiateType( : instanceProducer.produceBeanInstance( typeImplementorClass ); } else { - final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class ); - final ManagedBean typeBean = name != null + final ManagedBeanRegistry beanRegistry = serviceRegistry.requireService( ManagedBeanRegistry.class ); + final ManagedBean typeBean = name != null ? beanRegistry.getBean( name, typeImplementorClass, instanceProducer ) : beanRegistry.getBean( typeImplementorClass, instanceProducer ); return typeBean.getBeanInstance(); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotationBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotationBinder.java index 5f64d578560e..562a3aacaf1f 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotationBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotationBinder.java @@ -48,6 +48,7 @@ import org.hibernate.boot.model.convert.spi.RegisteredConversion; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.spi.BootstrapContext; import org.hibernate.boot.spi.InFlightMetadataCollector; import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.dialect.Dialect; @@ -601,6 +602,8 @@ private static void bindUserTypeRegistrations( private static void handleUserTypeRegistration( MetadataBuildingContext context, TypeRegistration compositeTypeRegistration) { + // TODO: check that the two classes agree, i.e. that + // the user type knows how to handle the type context.getMetadataCollector().registerUserType( compositeTypeRegistration.basicClass(), compositeTypeRegistration.userType() @@ -610,6 +613,8 @@ private static void handleUserTypeRegistration( private static void handleCompositeUserTypeRegistration( MetadataBuildingContext context, CompositeTypeRegistration compositeTypeRegistration) { + // TODO: check that the two classes agree, i.e. that + // the user type knows how to handle the type context.getMetadataCollector().registerCompositeUserType( compositeTypeRegistration.embeddableClass(), compositeTypeRegistration.userType() @@ -755,25 +760,21 @@ public Dialect getDialect() { } private static JdbcMapping resolveUserType(Class> userTypeClass, MetadataBuildingContext context) { - final UserType userType; - if ( context.getBuildingOptions().disallowExtensionsInCdi() ) { - userType = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( userTypeClass ); - } - else { - final StandardServiceRegistry serviceRegistry = context.getBootstrapContext().getServiceRegistry(); - final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class ); - userType = beanRegistry.getBean( userTypeClass ).getBeanInstance(); - } - + final UserType userType = context.getBuildingOptions().disallowExtensionsInCdi() + ? FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( userTypeClass ) + : context.getBootstrapContext().getServiceRegistry() + .requireService( ManagedBeanRegistry.class ) + .getBean( userTypeClass ).getBeanInstance(); return new CustomType<>( userType, context.getBootstrapContext().getTypeConfiguration() ); } private static JdbcMapping resolveAttributeConverter(Class> type, MetadataBuildingContext context) { - final StandardServiceRegistry serviceRegistry = context.getBootstrapContext().getServiceRegistry(); - final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class ); + final BootstrapContext bootstrapContext = context.getBootstrapContext(); + final ManagedBeanRegistry beanRegistry = + bootstrapContext.getServiceRegistry().requireService( ManagedBeanRegistry.class ); final ManagedBean> bean = beanRegistry.getBean( type ); - final TypeConfiguration typeConfiguration = context.getBootstrapContext().getTypeConfiguration(); + final TypeConfiguration typeConfiguration = bootstrapContext.getTypeConfiguration(); final JavaTypeRegistry jtdRegistry = typeConfiguration.getJavaTypeRegistry(); final JavaType> converterJtd = jtdRegistry.resolveDescriptor( bean.getBeanClass() ); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/UserTypeResolution.java b/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/UserTypeResolution.java index 6c710ac57b9d..0e60026cc429 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/UserTypeResolution.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/UserTypeResolution.java @@ -20,9 +20,9 @@ /** * @author Steve Ebersole */ -public class UserTypeResolution implements BasicValue.Resolution { - private final CustomType userTypeAdapter; - private final MutabilityPlan mutabilityPlan; +public class UserTypeResolution implements BasicValue.Resolution { + private final CustomType userTypeAdapter; + private final MutabilityPlan mutabilityPlan; /** * We need this for the way envers interprets the boot-model @@ -31,8 +31,8 @@ public class UserTypeResolution implements BasicValue.Resolution { private final Properties combinedTypeParameters; public UserTypeResolution( - CustomType userTypeAdapter, - MutabilityPlan explicitMutabilityPlan, + CustomType userTypeAdapter, + MutabilityPlan explicitMutabilityPlan, Properties combinedTypeParameters) { this.userTypeAdapter = userTypeAdapter; this.combinedTypeParameters = combinedTypeParameters; @@ -42,7 +42,7 @@ public UserTypeResolution( } @Override - public JavaType getDomainJavaType() { + public JavaType getDomainJavaType() { return userTypeAdapter.getJavaTypeDescriptor(); } @@ -57,7 +57,7 @@ public JdbcType getJdbcType() { } @Override - public BasicValueConverter getValueConverter() { + public BasicValueConverter getValueConverter() { // Even though we could expose the value converter of the user type here, // we can not do it, as the conversion is done behind the scenes in the binder/extractor, // whereas the converter returned here would, AFAIU, be used to construct a converted attribute mapping @@ -65,12 +65,12 @@ public BasicValueConverter getValueConverter() { } @Override - public MutabilityPlan getMutabilityPlan() { + public MutabilityPlan getMutabilityPlan() { return mutabilityPlan; } @Override - public BasicType getLegacyResolvedBasicType() { + public BasicType getLegacyResolvedBasicType() { return userTypeAdapter; } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java index 898912ac2136..71647bf40a1a 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java @@ -147,7 +147,6 @@ import org.hibernate.mapping.UniqueKey; import org.hibernate.mapping.Value; import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer; -import org.hibernate.resource.beans.spi.ManagedBean; import org.hibernate.resource.beans.spi.ManagedBeanRegistry; import org.hibernate.spi.NavigablePath; import org.hibernate.tuple.GenerationTiming; @@ -156,6 +155,7 @@ import org.hibernate.type.CustomType; import org.hibernate.type.ForeignKeyDirection; import org.hibernate.type.StandardBasicTypes; +import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.usertype.CompositeUserType; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; @@ -2349,13 +2349,11 @@ private BasicType resolveExplicitlyNamedAnyDiscriminatorType( Map parameters, Any.MetaValue discriminatorMapping) { final BootstrapContext bootstrapContext = metadataBuildingContext.getBootstrapContext(); + final TypeConfiguration typeConfiguration = bootstrapContext.getTypeConfiguration(); if ( isEmpty( parameters ) ) { // can use a standard one - final BasicType basicTypeByName = bootstrapContext - .getTypeConfiguration() - .getBasicTypeRegistry() - .getRegisteredType( typeName ); + final BasicType basicTypeByName = typeConfiguration.getBasicTypeRegistry().getRegisteredType( typeName ); if ( basicTypeByName != null ) { return basicTypeByName; } @@ -2368,7 +2366,7 @@ private BasicType resolveExplicitlyNamedAnyDiscriminatorType( parameters, null, metadataBuildingContext, - bootstrapContext.getTypeConfiguration().getCurrentBaseSqlTypeIndicators() + typeConfiguration.getCurrentBaseSqlTypeIndicators() ); if ( resolution.getCombinedTypeParameters() != null ) { @@ -2377,56 +2375,50 @@ private BasicType resolveExplicitlyNamedAnyDiscriminatorType( return resolution.getLegacyResolvedBasicType(); } + else { + final ClassLoaderService classLoaderService = + bootstrapContext.getServiceRegistry().requireService( ClassLoaderService.class ); + try { + final Object typeInstance = typeInstance( typeName, classLoaderService.classForName( typeName ) ); - final ClassLoaderService classLoaderService = bootstrapContext - .getServiceRegistry() - .getService( ClassLoaderService.class ); - - try { - final Class typeJavaType = classLoaderService.classForName( typeName ); - final Object typeInstance; - if ( metadataBuildingContext.getBuildingOptions().disallowExtensionsInCdi() ) { - typeInstance = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( typeJavaType ); - } - else { - final ManagedBeanRegistry beanRegistry = bootstrapContext - .getServiceRegistry() - .getService( ManagedBeanRegistry.class ); - final String beanName = typeName + ":" + TypeDefinition.NAME_COUNTER.getAndIncrement(); - final ManagedBean bean = beanRegistry.getBean( beanName, typeJavaType ); - typeInstance = bean.getBeanInstance(); - } + if ( typeInstance instanceof ParameterizedType ) { + if ( parameters != null ) { + Properties properties = new Properties(); + properties.putAll( parameters ); + ( (ParameterizedType) typeInstance ).setParameterValues( properties ); + } + } - if ( typeInstance instanceof ParameterizedType ) { - if ( parameters != null ) { - Properties properties = new Properties(); - properties.putAll( parameters ); - ( (ParameterizedType) typeInstance ).setParameterValues( properties ); + if ( typeInstance instanceof UserType ) { + return new CustomType<>( (UserType) typeInstance, typeConfiguration); } - } - if ( typeInstance instanceof UserType ) { - //noinspection unchecked - return new CustomType<>( - (UserType) typeInstance, - bootstrapContext.getTypeConfiguration() - ); + return (BasicType) typeInstance; + } + catch (ClassLoadingException e) { + log.debugf( "Unable to load explicit any-discriminator type name as Java Class - %s", typeName ); } - assert typeInstance instanceof BasicType; - return (BasicType) typeInstance; - } - catch (ClassLoadingException e) { - log.debugf( "Unable to load explicit any-discriminator type name as Java Class - %s", typeName ); + throw new org.hibernate.MappingException( + String.format( + Locale.ROOT, + "Unable to resolve explicit any-discriminator type name - %s", + typeName + ) + ); } + } - throw new org.hibernate.MappingException( - String.format( - Locale.ROOT, - "Unable to resolve explicit any-discriminator type name - %s", - typeName - ) - ); + private Object typeInstance(String typeName, Class typeJavaType) { + if ( metadataBuildingContext.getBuildingOptions().disallowExtensionsInCdi() ) { + return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( typeJavaType ); + } + else { + final String beanName = typeName + ":" + TypeDefinition.NAME_COUNTER.getAndIncrement(); + return metadataBuildingContext.getBootstrapContext() + .getServiceRegistry().requireService( ManagedBeanRegistry.class ) + .getBean( beanName, typeJavaType ).getBeanInstance(); + } } private void prepareValueTypeViaReflection( diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/BasicTypeRegistration.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/BasicTypeRegistration.java index 9cdcee02d8da..6f58794f7d6e 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/spi/BasicTypeRegistration.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/BasicTypeRegistration.java @@ -28,8 +28,7 @@ public BasicTypeRegistration(BasicType basicType, String[] registrationKeys) } public BasicTypeRegistration(UserType type, String[] keys, TypeConfiguration typeConfiguration) { - //noinspection unchecked - this( new CustomType<>( (UserType) type, keys, typeConfiguration ), keys ); + this( new CustomType<>( type, keys, typeConfiguration ), keys ); } public BasicType getBasicType() { diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java index c1ef735c4336..38a7b5756119 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java @@ -250,7 +250,7 @@ public static java.lang.reflect.Type reflectedPropertyType( String name, ClassLoaderService classLoaderService) throws MappingException { try { - Class clazz = classLoaderService.classForName( className ); + Class clazz = classLoaderService.classForName( className ); return getter( clazz, name ).getReturnType(); } catch ( ClassLoadingException e ) { @@ -368,7 +368,7 @@ public static Constructor getConstructor( try { constructor = clazz.getDeclaredConstructor( constructorArgs ); try { - ReflectHelper.ensureAccessibility( constructor ); + ensureAccessibility( constructor ); } catch ( SecurityException e ) { constructor = null; @@ -425,11 +425,9 @@ else if ( containerClass == Object.class ) { } public static void ensureAccessibility(AccessibleObject accessibleObject) { - if ( accessibleObject.isAccessible() ) { - return; + if ( !accessibleObject.isAccessible() ) { + accessibleObject.setAccessible( true ); } - - accessibleObject.setAccessible( true ); } private static Field locateField(Class clazz, String propertyName) { diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java b/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java index ca6f276da41b..e3806d1b8f5c 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java @@ -67,6 +67,7 @@ import jakarta.persistence.TemporalType; import static java.lang.Boolean.parseBoolean; +import static org.hibernate.internal.util.collections.CollectionHelper.isNotEmpty; import static org.hibernate.mapping.MappingHelper.injectParameters; /** @@ -260,14 +261,14 @@ private void checkSelectable(Selectable incomingColumn) { final Selectable column = getColumn(); if ( column == incomingColumn || column.getText().equals( incomingColumn.getText() ) ) { log.debugf( "Skipping column re-registration: %s.%s", getTable().getName(), column.getText() ); - return; } - -// throw new IllegalStateException( -// "BasicValue [" + ownerName + "." + propertyName + -// "] already had column associated: `" + column.getText() + -// "` -> `" + incomingColumn.getText() + "`" -// ); +// else { +// throw new IllegalStateException( +// "BasicValue [" + ownerName + "." + propertyName + +// "] already had column associated: `" + column.getText() + +// "` -> `" + incomingColumn.getText() + "`" +// ); +// } } @Override @@ -390,12 +391,13 @@ public SelectablePath createSelectablePath(String selectableName) { } protected Resolution buildResolution() { - Properties typeParameters = getTypeParameters(); + final Properties typeParameters = getTypeParameters(); if ( typeParameters != null && parseBoolean( typeParameters.getProperty(DynamicParameterizedType.IS_DYNAMIC) ) && typeParameters.get(DynamicParameterizedType.PARAMETER_TYPE) == null ) { createParameterImpl(); } + if ( explicitTypeName != null ) { return interpretExplicitlyNamedType( explicitTypeName, @@ -410,108 +412,115 @@ && parseBoolean( typeParameters.getProperty(DynamicParameterizedType.IS_DYNAMIC) ); } - if ( isVersion() ) { return VersionResolution.from( implicitJavaTypeAccess, timeZoneStorageType, getBuildingContext() ); } // determine JavaType if we can - - final BasicJavaType explicitJavaType = explicitJavaTypeAccess == null ? null - : explicitJavaTypeAccess.apply( getTypeConfiguration() ); - + final BasicJavaType explicitJavaType = + explicitJavaTypeAccess == null ? null : explicitJavaTypeAccess.apply( getTypeConfiguration() ); final JavaType javaType = determineJavaType( explicitJavaType ); final ConverterDescriptor attributeConverterDescriptor = getAttributeConverterDescriptor(); - final Selectable column = getColumn(); - if ( attributeConverterDescriptor != null ) { - final ManagedBeanRegistry managedBeanRegistry = getServiceRegistry().getService( ManagedBeanRegistry.class ); - - final NamedConverterResolution converterResolution = NamedConverterResolution.from( - attributeConverterDescriptor, - explicitJavaTypeAccess, - explicitJdbcTypeAccess, - explicitMutabilityPlanAccess, - this, - new JpaAttributeConverterCreationContext() { - @Override - public ManagedBeanRegistry getManagedBeanRegistry() { - return managedBeanRegistry; - } - @Override - public TypeConfiguration getTypeConfiguration() { - return BasicValue.this.getTypeConfiguration(); - } - }, - getBuildingContext() - ); - - if ( javaType instanceof BasicPluralJavaType - && !attributeConverterDescriptor.getDomainValueResolvedType() - .getErasedType() - .isAssignableFrom( javaType.getJavaTypeClass() ) ) { - // In this case, the converter applies to the element of a BasicPluralJavaType - final BasicPluralJavaType containerJtd = (BasicPluralJavaType) javaType; - final BasicType registeredElementType = converterResolution.getLegacyResolvedBasicType(); - final BasicType registeredType = registeredElementType == null ? null - : containerJtd.resolveType( - getTypeConfiguration(), - getDialect(), - registeredElementType, - column instanceof ColumnTypeInformation ? (ColumnTypeInformation) column : null, - this - ); - if ( registeredType != null ) { - getTypeConfiguration().getBasicTypeRegistry().register( registeredType ); - - return new InferredBasicValueResolution( - registeredType, - registeredType.getJavaTypeDescriptor(), - registeredType.getJavaTypeDescriptor(), - registeredType.getJdbcType(), - registeredType, - null - ); - } - } + return attributeConverterDescriptor != null + ? converterResolution( javaType, attributeConverterDescriptor ) + : resolution( explicitJavaType, javaType ); + } - return converterResolution; + private Resolution resolution(BasicJavaType explicitJavaType, JavaType javaType) { + final JavaType basicJavaType; + final JdbcType jdbcType; + if ( explicitJdbcTypeAccess != null ) { + final TypeConfiguration typeConfiguration = getTypeConfiguration(); + jdbcType = explicitJdbcTypeAccess.apply( typeConfiguration ); + basicJavaType = javaType == null && jdbcType != null + ? jdbcType.getJdbcRecommendedJavaTypeMapping(null, null, typeConfiguration) + : javaType; + } + else { + jdbcType = null; + basicJavaType = javaType; } - - final JdbcType jdbcType = explicitJdbcTypeAccess != null - ? explicitJdbcTypeAccess.apply( getTypeConfiguration() ) - : null; - - final JavaType basicJavaType = javaType == null && jdbcType != null - ? jdbcType.getJdbcRecommendedJavaTypeMapping( null, null, getTypeConfiguration() ) - : javaType; if ( basicJavaType == null ) { throw new MappingException( "Unable to determine JavaType to use : " + this ); } - final TypeDefinition autoAppliedTypeDef = basicJavaType instanceof BasicJavaType - ? getBuildingContext().getTypeDefinitionRegistry().resolveAutoApplied( (BasicJavaType) basicJavaType ) - : null; - if ( autoAppliedTypeDef != null + if ( basicJavaType instanceof BasicJavaType && ( !basicJavaType.getJavaTypeClass().isEnum() || enumerationStyle == null ) ) { - log.debug( "BasicValue resolution matched auto-applied type-definition" ); - return autoAppliedTypeDef.resolve( typeParameters, null, getBuildingContext(), this ); + final TypeDefinition autoAppliedTypeDef = + getBuildingContext().getTypeDefinitionRegistry() + .resolveAutoApplied( (BasicJavaType) basicJavaType ); + if ( autoAppliedTypeDef != null ) { + log.debug("BasicValue resolution matched auto-applied type-definition"); + return autoAppliedTypeDef.resolve( getTypeParameters(), null, getBuildingContext(), this ); + } } - else { - return InferredBasicValueResolver.from( - explicitJavaType, - jdbcType, - resolvedJavaType, - this::determineReflectedJavaType, - explicitMutabilityPlanAccess, - this, - getTable(), - column, - ownerName, - propertyName, - getBuildingContext() + + return InferredBasicValueResolver.from( + explicitJavaType, + jdbcType, + resolvedJavaType, + this::determineReflectedJavaType, + explicitMutabilityPlanAccess, + this, + getTable(), + getColumn(), + ownerName, + propertyName, + getBuildingContext() + ); + } + + private Resolution converterResolution(JavaType javaType, ConverterDescriptor attributeConverterDescriptor) { + final ManagedBeanRegistry managedBeanRegistry = getServiceRegistry().getService( ManagedBeanRegistry.class ); + final NamedConverterResolution converterResolution = NamedConverterResolution.from( + attributeConverterDescriptor, + explicitJavaTypeAccess, + explicitJdbcTypeAccess, + explicitMutabilityPlanAccess, + this, + new JpaAttributeConverterCreationContext() { + @Override + public ManagedBeanRegistry getManagedBeanRegistry() { + return managedBeanRegistry; + } + @Override + public TypeConfiguration getTypeConfiguration() { + return BasicValue.this.getTypeConfiguration(); + } + }, + getBuildingContext() + ); + + if ( javaType instanceof BasicPluralJavaType + && !attributeConverterDescriptor.getDomainValueResolvedType().getErasedType() + .isAssignableFrom( javaType.getJavaTypeClass() ) ) { + // In this case, the converter applies to the element of a BasicPluralJavaType + final BasicPluralJavaType containerJtd = (BasicPluralJavaType) javaType; + final BasicType registeredElementType = converterResolution.getLegacyResolvedBasicType(); + final Selectable column = getColumn(); + final BasicType registeredType = registeredElementType == null ? null + : containerJtd.resolveType( + getTypeConfiguration(), + getDialect(), + registeredElementType, + column instanceof ColumnTypeInformation ? (ColumnTypeInformation) column : null, + this ); + if ( registeredType != null ) { + getTypeConfiguration().getBasicTypeRegistry().register( registeredType ); + return new InferredBasicValueResolution( + registeredType, + registeredType.getJavaTypeDescriptor(), + registeredType.getJavaTypeDescriptor(), + registeredType.getJdbcType(), + registeredType, + null + ); + } } + + return converterResolution; } private JavaType determineJavaType(JavaType explicitJavaType) { @@ -549,7 +558,7 @@ else if ( ownerName != null && propertyName != null ) { impliedJavaType = ReflectHelper.reflectedPropertyType( ownerName, propertyName, - getServiceRegistry().getService( ClassLoaderService.class ) + getServiceRegistry().requireService( ClassLoaderService.class ) ); } else { @@ -666,7 +675,7 @@ public TypeConfiguration getTypeConfiguration() { // see if the name is a UserType or BasicType implementor class name - final ClassLoaderService cls = serviceRegistry.getService( ClassLoaderService.class ); + final ClassLoaderService cls = serviceRegistry.requireService( ClassLoaderService.class ); try { final Class typeNamedClass = cls.classForName( name ); @@ -779,7 +788,7 @@ public void setTypeName(String typeName) { if ( StringHelper.isNotEmpty( typeName ) ) { if ( typeName.startsWith( ConverterDescriptor.TYPE_NAME_PREFIX ) ) { final String converterClassName = typeName.substring( ConverterDescriptor.TYPE_NAME_PREFIX.length() ); - final ClassLoaderService cls = getServiceRegistry().getService( ClassLoaderService.class ); + final ClassLoaderService cls = getServiceRegistry().requireService( ClassLoaderService.class ); try { final Class> converterClass = cls.classForName( converterClassName ); setAttributeConverterDescriptor( new ClassBasedConverterDescriptor( @@ -803,65 +812,70 @@ public void setTypeName(String typeName) { private static int COUNTER; - public > void setExplicitCustomType(Class explicitCustomType) { + public void setExplicitCustomType(Class> explicitCustomType) { if ( explicitCustomType != null ) { if ( resolution != null ) { throw new UnsupportedOperationException( "Unsupported attempt to set an explicit-custom-type when value is already resolved" ); } - - final BeanInstanceProducer instanceProducer = - getBuildingContext().getBootstrapContext().getCustomTypeProducer(); - - final Properties properties = new Properties(); - if ( CollectionHelper.isNotEmpty( getTypeParameters() ) ) { - properties.putAll( getTypeParameters() ); - } - if ( CollectionHelper.isNotEmpty( explicitLocalTypeParams ) ) { - properties.putAll( explicitLocalTypeParams ); + else { + resolution = new UserTypeResolution<>( + new CustomType<>( + getConfiguredUserTypeBean( explicitCustomType, getCustomTypeProperties() ), + getTypeConfiguration() + ), + null, + getCustomTypeProperties() + ); } + } + } - final T typeInstance; - if ( getBuildingContext().getBuildingOptions().disallowExtensionsInCdi() ) { - typeInstance = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( explicitCustomType ); - } - else { - final boolean hasParameters = CollectionHelper.isNotEmpty( properties ); + private Properties getCustomTypeProperties() { + final Properties properties = new Properties(); + if ( isNotEmpty( getTypeParameters() ) ) { + properties.putAll( getTypeParameters() ); + } + if ( isNotEmpty( explicitLocalTypeParams ) ) { + properties.putAll( explicitLocalTypeParams ); + } + return properties; + } - final ManagedBean typeBean; - if ( hasParameters ) { - final String name = explicitCustomType.getName() + COUNTER++; - typeBean = getServiceRegistry().getService( ManagedBeanRegistry.class ) - .getBean( name, explicitCustomType, instanceProducer ); - } - else { - typeBean = getServiceRegistry().getService( ManagedBeanRegistry.class ) - .getBean( explicitCustomType, instanceProducer ); - } - typeInstance = typeBean.getBeanInstance(); - } + private UserType getConfiguredUserTypeBean(Class> explicitCustomType, Properties properties) { + final UserType typeInstance = + getBuildingContext().getBuildingOptions().disallowExtensionsInCdi() + ? FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( explicitCustomType ) + : getUserTypeBean( explicitCustomType, properties ).getBeanInstance(); - if ( typeInstance instanceof TypeConfigurationAware ) { - ( (TypeConfigurationAware) typeInstance ).setTypeConfiguration( getTypeConfiguration() ); - } + if ( typeInstance instanceof TypeConfigurationAware ) { + final TypeConfigurationAware configurationAware = (TypeConfigurationAware) typeInstance; + configurationAware.setTypeConfiguration( getTypeConfiguration() ); + } - if ( typeInstance instanceof DynamicParameterizedType ) { - if (parseBoolean(properties.getProperty(DynamicParameterizedType.IS_DYNAMIC))) { - if (properties.get(DynamicParameterizedType.PARAMETER_TYPE) == null) { - final DynamicParameterizedType.ParameterType parameterType = makeParameterImpl(); - properties.put(DynamicParameterizedType.PARAMETER_TYPE, parameterType); - } + if ( typeInstance instanceof DynamicParameterizedType ) { + if ( parseBoolean( properties.getProperty( DynamicParameterizedType.IS_DYNAMIC ) ) ) { + if ( properties.get( DynamicParameterizedType.PARAMETER_TYPE ) == null ) { + properties.put( DynamicParameterizedType.PARAMETER_TYPE, makeParameterImpl() ); } } + } - injectParameters( typeInstance, properties ); - // envers - grr - setTypeParameters( properties ); + injectParameters( typeInstance, properties); + // envers - grr + setTypeParameters( properties ); - this.resolution = new UserTypeResolution( - new CustomType<>( (UserType) typeInstance, getTypeConfiguration() ), - null, - properties - ); + return typeInstance; + } + + private ManagedBean getUserTypeBean(Class explicitCustomType, Properties properties) { + final BeanInstanceProducer producer = getBuildingContext().getBootstrapContext().getCustomTypeProducer(); + final ManagedBeanRegistry registry = getServiceRegistry().requireService( ManagedBeanRegistry.class ); + if ( isNotEmpty( properties ) ) { + final String name = explicitCustomType.getName() + COUNTER++; + return registry.getBean( name, explicitCustomType, producer ); + } + else { + return registry.getBean( explicitCustomType, producer ); } } @@ -882,9 +896,9 @@ public Object accept(ValueVisitor visitor) { @Internal public boolean isDisallowedWrapperArray() { return getBuildingContext().getBuildingOptions().getWrapperArrayHandling() == WrapperArrayHandling.DISALLOW - && !isLob() - && ( explicitJavaTypeAccess == null || explicitJavaTypeAccess.apply( getTypeConfiguration() ) == null ) - && isWrapperByteOrCharacterArray(); + && !isLob() + && ( explicitJavaTypeAccess == null || explicitJavaTypeAccess.apply( getTypeConfiguration() ) == null ) + && isWrapperByteOrCharacterArray(); } private boolean isWrapperByteOrCharacterArray() { diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java b/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java index e8579208d9e8..401b47bf632d 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java @@ -957,6 +957,7 @@ protected void createParameterImpl() { throw new MappingException( "Could not create DynamicParameterizedType for type: " + typeName, e ); } } + public DynamicParameterizedType.ParameterType makeParameterImpl() { try { final String[] columnNames = new String[ columns.size() ]; diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/ResultMementoBasicStandard.java b/hibernate-core/src/main/java/org/hibernate/query/internal/ResultMementoBasicStandard.java index 7781442b3c8f..78a2bbd06239 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/internal/ResultMementoBasicStandard.java +++ b/hibernate-core/src/main/java/org/hibernate/query/internal/ResultMementoBasicStandard.java @@ -113,16 +113,19 @@ else if ( AttributeConverter.class.isAssignableFrom( definedType ) ) { else { final JavaTypeRegistry jtdRegistry = typeConfiguration.getJavaTypeRegistry(); final JavaType registeredJtd = jtdRegistry.getDescriptor( definition.type() ); - final ManagedBeanRegistry beanRegistry = sessionFactory.getServiceRegistry().getService( ManagedBeanRegistry.class ); + final ManagedBeanRegistry beanRegistry = + sessionFactory.getServiceRegistry().requireService( ManagedBeanRegistry.class ); if ( BasicType.class.isAssignableFrom( registeredJtd.getJavaTypeClass() ) ) { - final ManagedBean> typeBean = (ManagedBean) beanRegistry.getBean( registeredJtd.getJavaTypeClass() ); + final ManagedBean> typeBean = + (ManagedBean) beanRegistry.getBean( registeredJtd.getJavaTypeClass() ); explicitType = typeBean.getBeanInstance(); explicitJavaType = explicitType.getJavaTypeDescriptor(); } else if ( UserType.class.isAssignableFrom( registeredJtd.getJavaTypeClass() ) ) { - final ManagedBean> userTypeBean = (ManagedBean) beanRegistry.getBean( registeredJtd.getJavaTypeClass() ); + final ManagedBean> userTypeBean = + (ManagedBean) beanRegistry.getBean( registeredJtd.getJavaTypeClass() ); // todo (6.0) : is this the best approach? or should we keep a Class -> @Type mapping somewhere? - explicitType = new CustomType<>( (UserType) userTypeBean.getBeanInstance(), typeConfiguration ); + explicitType = new CustomType<>( userTypeBean.getBeanInstance(), typeConfiguration ); explicitJavaType = explicitType.getJavaTypeDescriptor(); } else { diff --git a/hibernate-core/src/main/java/org/hibernate/type/CustomType.java b/hibernate-core/src/main/java/org/hibernate/type/CustomType.java index 511fd6abe48c..9ebeb90a9e60 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/CustomType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/CustomType.java @@ -68,7 +68,8 @@ public CustomType(UserType userType, TypeConfiguration typeConfiguration) thr this( userType, ArrayHelper.EMPTY_STRING_ARRAY, typeConfiguration ); } - public CustomType(UserType userType, String[] registrationKeys, TypeConfiguration typeConfiguration) throws MappingException { + public CustomType(UserType userType, String[] registrationKeys, TypeConfiguration typeConfiguration) + throws MappingException { this.userType = userType; name = userType.getClass().getName();