From b6d7655a06d06a9fea3e786995f20784c0e13022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Thu, 2 Jan 2025 13:32:18 +0100 Subject: [PATCH 01/11] HHH-18976 Forbid any future new uses of Array.newInstance --- .../collection/spi/PersistentArrayHolder.java | 2 ++ .../org/hibernate/dialect/JsonHelper.java | 2 ++ .../dialect/function/array/DdlTypeHelper.java | 2 ++ ...yViaElementArgumentReturnTypeResolver.java | 2 ++ .../internal/EventListenerGroupImpl.java | 2 ++ .../internal/EventListenerRegistryImpl.java | 2 ++ .../internal/build/AllowReflection.java | 18 +++++++++++++++++ .../util/collections/ArrayHelper.java | 4 ++++ .../event/internal/CallbackRegistryImpl.java | 2 ++ .../AbstractCollectionBatchLoader.java | 2 ++ .../internal/AbstractMultiIdEntityLoader.java | 2 ++ .../CollectionBatchLoaderArrayParam.java | 4 ++++ .../internal/EntityBatchLoaderArrayParam.java | 3 +++ .../loader/ast/internal/LoaderHelper.java | 2 ++ .../results/internal/StandardRowReader.java | 2 ++ .../java/org/hibernate/type/ArrayType.java | 2 ++ .../converter/internal/ArrayConverter.java | 2 ++ .../internal/CollectionConverter.java | 2 ++ .../java/AbstractArrayJavaType.java | 2 ++ .../type/descriptor/java/ArrayJavaType.java | 3 +++ .../descriptor/java/ArrayMutabilityPlan.java | 3 +++ .../java/BooleanPrimitiveArrayJavaType.java | 2 ++ .../java/DoublePrimitiveArrayJavaType.java | 2 ++ .../java/FloatPrimitiveArrayJavaType.java | 2 ++ .../java/IntegerPrimitiveArrayJavaType.java | 2 ++ .../java/LongPrimitiveArrayJavaType.java | 2 ++ .../java/ShortPrimitiveArrayJavaType.java | 2 ++ .../java/spi/BasicCollectionJavaType.java | 2 ++ .../type/descriptor/jdbc/ArrayJdbcType.java | 2 ++ .../type/format/jaxb/JaxbXmlFormatMapper.java | 2 ++ .../src/main/groovy/local.code-quality.gradle | 6 +++++- rules/forbidden-apis.txt | 20 +++++++++++++++++++ 32 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/internal/build/AllowReflection.java create mode 100644 rules/forbidden-apis.txt diff --git a/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentArrayHolder.java b/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentArrayHolder.java index 426ca5b88ddb..755cf16840c6 100644 --- a/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentArrayHolder.java +++ b/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentArrayHolder.java @@ -18,6 +18,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.type.Type; @@ -34,6 +35,7 @@ * @author Gavin King */ @Incubating +@AllowReflection // We need the ability to create arrays of the same type as in the model. public class PersistentArrayHolder extends AbstractPersistentCollection { private static final CoreMessageLogger LOG = CoreLogging.messageLogger( PersistentArrayHolder.class ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/JsonHelper.java b/hibernate-core/src/main/java/org/hibernate/dialect/JsonHelper.java index 76594c74c14e..ce50d1b6f587 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/JsonHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/JsonHelper.java @@ -18,6 +18,7 @@ import java.util.Objects; import org.hibernate.Internal; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.internal.util.CharSequenceHelper; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.metamodel.mapping.EmbeddableMappingType; @@ -1612,6 +1613,7 @@ public Object[] toArray() { } @Override + @AllowReflection // We need the ability to create arrays of requested types dynamically. public T[] toArray(T[] a) { //noinspection unchecked final T[] r = a.length >= size diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/DdlTypeHelper.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/DdlTypeHelper.java index c4beb0c99c3e..154bd16f7a1c 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/DdlTypeHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/DdlTypeHelper.java @@ -10,6 +10,7 @@ import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.Size; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.metamodel.mapping.JdbcMappingContainer; import org.hibernate.metamodel.mapping.SqlTypedMapping; import org.hibernate.metamodel.model.domain.DomainType; @@ -24,6 +25,7 @@ public class DdlTypeHelper { @SuppressWarnings("unchecked") + @AllowReflection public static BasicType resolveArrayType(DomainType elementType, TypeConfiguration typeConfiguration) { @SuppressWarnings("unchecked") final BasicPluralJavaType arrayJavaType = (BasicPluralJavaType) typeConfiguration.getJavaTypeRegistry() .getDescriptor( diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/JsonArrayViaElementArgumentReturnTypeResolver.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/JsonArrayViaElementArgumentReturnTypeResolver.java index 97a5228b6c69..10605215124e 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/JsonArrayViaElementArgumentReturnTypeResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/JsonArrayViaElementArgumentReturnTypeResolver.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.function.Supplier; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.metamodel.mapping.BasicValuedMapping; import org.hibernate.metamodel.mapping.MappingModelExpressible; import org.hibernate.metamodel.model.domain.DomainType; @@ -78,6 +79,7 @@ public BasicValuedMapping resolveFunctionReturnType( return null; } + @AllowReflection public static BasicType resolveJsonArrayType(DomainType elementType, TypeConfiguration typeConfiguration) { final Class arrayClass = Array.newInstance( elementType.getBindableJavaType(), 0 ).getClass(); @SuppressWarnings("unchecked") diff --git a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerGroupImpl.java b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerGroupImpl.java index 840516bba6e1..3d9081ad082b 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerGroupImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerGroupImpl.java @@ -22,6 +22,7 @@ import org.hibernate.event.service.spi.EventListenerRegistrationException; import org.hibernate.event.service.spi.JpaBootstrapSensitive; import org.hibernate.event.spi.EventType; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.jpa.event.spi.CallbackRegistry; import org.hibernate.jpa.event.spi.CallbackRegistryConsumer; @@ -350,6 +351,7 @@ private void handleListenerAddition(T listener, Consumer additionHandler) { } @SuppressWarnings("unchecked") + @AllowReflection // Possible array types are registered in org.hibernate.graalvm.internal.StaticClassLists.typesNeedingArrayCopy private T[] createListenerArrayForWrite(int len) { return (T[]) Array.newInstance( eventType.baseListenerInterface(), len ); } diff --git a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerRegistryImpl.java b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerRegistryImpl.java index 95111991da73..0d1247ac9a2a 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerRegistryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/event/service/internal/EventListenerRegistryImpl.java @@ -38,6 +38,7 @@ import org.hibernate.event.service.spi.EventListenerRegistrationException; import org.hibernate.event.service.spi.EventListenerRegistry; import org.hibernate.event.spi.EventType; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.jpa.event.spi.CallbackRegistry; import static org.hibernate.event.spi.EventType.AUTO_FLUSH; @@ -122,6 +123,7 @@ public final void setListeners(EventType type, Class... list } @SafeVarargs + @AllowReflection // Possible array types are registered in org.hibernate.graalvm.internal.StaticClassLists.typesNeedingArrayCopy private T[] resolveListenerInstances(EventType type, Class... listenerClasses) { @SuppressWarnings("unchecked") T[] listeners = (T[]) Array.newInstance( type.baseListenerInterface(), listenerClasses.length ); diff --git a/hibernate-core/src/main/java/org/hibernate/internal/build/AllowReflection.java b/hibernate-core/src/main/java/org/hibernate/internal/build/AllowReflection.java new file mode 100644 index 000000000000..456cd4574c09 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/internal/build/AllowReflection.java @@ -0,0 +1,18 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.internal.build; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; + +@Retention( RetentionPolicy.CLASS ) +@Target({ TYPE, METHOD, CONSTRUCTOR }) +public @interface AllowReflection { +} diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java index 79c115b981f6..556792813a32 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java @@ -18,6 +18,7 @@ import org.hibernate.HibernateException; import org.hibernate.LockMode; import org.hibernate.LockOptions; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.type.Type; public final class ArrayHelper { @@ -59,6 +60,7 @@ public static int indexOf(Object[] array, int end, Object object) { } @SuppressWarnings("unchecked") + @AllowReflection public static T[] filledArray(T value, Class valueJavaType, int size) { final T[] array = (T[]) Array.newInstance( valueJavaType, size ); Arrays.fill( array, value ); @@ -202,6 +204,7 @@ public static int[] join(int[] x, int[] y) { } @SuppressWarnings("unchecked") + @AllowReflection public static T[] join(T[] x, T... y) { T[] result = (T[]) Array.newInstance( x.getClass().getComponentType(), x.length + y.length ); System.arraycopy( x, 0, result, 0, x.length ); @@ -520,6 +523,7 @@ public static void forEach(T[] array, Consumer consumer) { } @SuppressWarnings("unchecked") + @AllowReflection public static T[] newInstance(Class elementType, int length) { return (T[]) Array.newInstance( elementType, length ); } diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/event/internal/CallbackRegistryImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/event/internal/CallbackRegistryImpl.java index 5c52ad61fda9..c65ee9116eaf 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/event/internal/CallbackRegistryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/event/internal/CallbackRegistryImpl.java @@ -9,6 +9,7 @@ import jakarta.persistence.PersistenceException; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.MapBackedClassValue; import org.hibernate.internal.util.collections.ReadOnlyMap; @@ -168,6 +169,7 @@ public static class Builder { private final Map, Callback[]> postUpdates = new HashMap<>(); private final Map, Callback[]> postLoads = new HashMap<>(); + @AllowReflection public void registerCallbacks(Class entityClass, Callback[] callbacks) { if ( callbacks != null ) { for ( Callback callback : callbacks ) { diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractCollectionBatchLoader.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractCollectionBatchLoader.java index b19ef0a592f0..7ac72a5222b2 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractCollectionBatchLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractCollectionBatchLoader.java @@ -11,6 +11,7 @@ import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.loader.ast.spi.CollectionBatchLoader; import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping; @@ -126,6 +127,7 @@ protected void finishInitializingKey(Object key, SharedSessionContractImplemento } + @AllowReflection Object[] resolveKeysToInitialize(Object keyBeingLoaded, SharedSessionContractImplementor session) { final int length = getDomainBatchSize(); final Object[] keysToInitialize = (Object[]) Array.newInstance( diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractMultiIdEntityLoader.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractMultiIdEntityLoader.java index 6d70c1076e4f..1e5e8951e1d2 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractMultiIdEntityLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractMultiIdEntityLoader.java @@ -11,6 +11,7 @@ import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.event.spi.EventSource; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.loader.ast.spi.MultiIdEntityLoader; import org.hibernate.loader.ast.spi.MultiIdLoadOptions; import org.hibernate.loader.internal.CacheLoadHelper.PersistenceContextEntry; @@ -42,6 +43,7 @@ public abstract class AbstractMultiIdEntityLoader implements MultiIdEntityLoa private final EntityIdentifierMapping identifierMapping; protected final Object[] idArray; + @AllowReflection public AbstractMultiIdEntityLoader(EntityMappingType entityDescriptor, SessionFactoryImplementor sessionFactory) { this.entityDescriptor = entityDescriptor; this.sessionFactory = sessionFactory; diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderArrayParam.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderArrayParam.java index c4b543734cfa..029dcd38671e 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderArrayParam.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderArrayParam.java @@ -13,6 +13,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SubselectFetch; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.loader.ast.spi.CollectionBatchLoader; import org.hibernate.loader.ast.spi.SqlArrayMultiKeyLoader; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; @@ -51,6 +52,7 @@ public class CollectionBatchLoaderArrayParam private final SelectStatement sqlSelect; private final JdbcOperationQuerySelect jdbcSelectOperation; + @AllowReflection public CollectionBatchLoaderArrayParam( int domainBatchSize, LoadQueryInfluencers loadQueryInfluencers, @@ -115,6 +117,7 @@ public PersistentCollection load(Object keyBeingLoaded, SharedSessionContract } + @AllowReflection private PersistentCollection loadEmbeddable( Object keyBeingLoaded, SharedSessionContractImplementor session, @@ -216,6 +219,7 @@ void finishInitializingKeys(Object[] keys, SharedSessionContractImplementor sess } @Override + @AllowReflection Object[] resolveKeysToInitialize(Object keyBeingLoaded, SharedSessionContractImplementor session) { final ForeignKeyDescriptor keyDescriptor = getLoadable().getKeyDescriptor(); if( keyDescriptor.isEmbedded()){ diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/EntityBatchLoaderArrayParam.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/EntityBatchLoaderArrayParam.java index 08cf5fd13bf5..3a5213eb19fb 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/EntityBatchLoaderArrayParam.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/EntityBatchLoaderArrayParam.java @@ -11,6 +11,7 @@ import org.hibernate.LockOptions; import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.loader.ast.spi.SqlArrayMultiKeyLoader; import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; @@ -58,6 +59,7 @@ public class EntityBatchLoaderArrayParam * {@link EntityIdentifierMapping} is not available at that time. On first use, we know we * have it available */ + @AllowReflection public EntityBatchLoaderArrayParam( int domainBatchSize, EntityMappingType entityDescriptor, @@ -106,6 +108,7 @@ public int getDomainBatchSize() { return domainBatchSize; } + @AllowReflection protected Object[] resolveIdsToInitialize(Object pkValue, SharedSessionContractImplementor session) { //TODO: should this really be different to EntityBatchLoaderInPredicate impl? final Class idType = identifierMapping.getJavaType().getJavaTypeClass(); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderHelper.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderHelper.java index 885b46e10def..3ad14036c4e3 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderHelper.java @@ -21,6 +21,7 @@ import org.hibernate.event.monitor.spi.EventMonitor; import org.hibernate.event.spi.EventSource; import org.hibernate.event.monitor.spi.DiagnosticEvent; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.loader.LoaderLogging; import org.hibernate.metamodel.mapping.BasicValuedModelPart; import org.hibernate.metamodel.mapping.EntityMappingType; @@ -202,6 +203,7 @@ public static K[] normalizeKeys( * @param elementClass The type of the array elements. See {@link Class#getComponentType()} * @param length The length to which the array should be created. This is usually zero for Hibernate uses */ + @AllowReflection public static X[] createTypedArray(Class elementClass, @SuppressWarnings("SameParameterValue") int length) { //noinspection unchecked return (X[]) Array.newInstance( elementClass, length ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java index 1e53ddbffe4a..a34b24fe6c4c 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java @@ -9,6 +9,7 @@ import java.util.List; import org.hibernate.engine.spi.EntityKey; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerData; @@ -130,6 +131,7 @@ public boolean hasCollectionInitializers() { } @Override + @AllowReflection public T readRow(RowProcessingState rowProcessingState) { coordinateInitializers( rowProcessingState ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/ArrayType.java b/hibernate-core/src/main/java/org/hibernate/type/ArrayType.java index 28083585deb3..68c570712195 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/ArrayType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/ArrayType.java @@ -16,6 +16,7 @@ import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.metamodel.CollectionClassification; import org.hibernate.persister.collection.CollectionPersister; @@ -26,6 +27,7 @@ * A type for persistent arrays. * @author Gavin King */ +@AllowReflection public class ArrayType extends CollectionType { private final Class elementClass; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/ArrayConverter.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/ArrayConverter.java index fa228e05adaf..520b46560f52 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/ArrayConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/ArrayConverter.java @@ -6,6 +6,7 @@ import java.lang.reflect.Array; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.type.descriptor.converter.spi.BasicValueConverter; import org.hibernate.type.descriptor.java.JavaType; @@ -18,6 +19,7 @@ * @param the unconverted array type * @param the converted array type */ +@AllowReflection public class ArrayConverter implements BasicValueConverter { private final BasicValueConverter elementConverter; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/CollectionConverter.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/CollectionConverter.java index 6e9c8bcc9938..c997d216b77a 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/CollectionConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/CollectionConverter.java @@ -7,6 +7,7 @@ import java.lang.reflect.Array; import java.util.Collection; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.type.descriptor.converter.spi.BasicValueConverter; import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.spi.BasicCollectionJavaType; @@ -43,6 +44,7 @@ public X toDomainValue(Y relationalForm) { } @Override + @AllowReflection public Y toRelationalValue(X domainForm) { if ( domainForm == null ) { return null; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java index c359ba704b01..333f2cce40a7 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java @@ -8,6 +8,7 @@ import org.hibernate.MappingException; import org.hibernate.dialect.Dialect; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation; import org.hibernate.type.descriptor.converter.internal.ArrayConverter; import org.hibernate.type.BasicArrayType; @@ -20,6 +21,7 @@ import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; import org.hibernate.type.spi.TypeConfiguration; +@AllowReflection public abstract class AbstractArrayJavaType extends AbstractClassJavaType implements BasicPluralJavaType { diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java index e129da661be1..7fb49c195ab3 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayJavaType.java @@ -14,6 +14,7 @@ import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.BinaryStream; import org.hibernate.engine.jdbc.internal.ArrayBackedBinaryStream; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.internal.util.SerializationHelper; import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation; import org.hibernate.type.BasicPluralType; @@ -29,6 +30,7 @@ * @author Christian Beikov * @author Jordan Gigov */ +@AllowReflection public class ArrayJavaType extends AbstractArrayJavaType { public ArrayJavaType(BasicType baseDescriptor) { @@ -376,6 +378,7 @@ private T[] fromBytes(byte[] bytes) { } } + @AllowReflection private static class ArrayMutabilityPlan implements MutabilityPlan { private final Class componentClass; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayMutabilityPlan.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayMutabilityPlan.java index db71278e10a7..892aaca02963 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayMutabilityPlan.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayMutabilityPlan.java @@ -3,6 +3,8 @@ * Copyright Red Hat Inc. and Hibernate Authors */ package org.hibernate.type.descriptor.java; +import org.hibernate.internal.build.AllowReflection; + import java.lang.reflect.Array; /** @@ -15,6 +17,7 @@ public class ArrayMutabilityPlan extends MutableMutabilityPlan { public static final ArrayMutabilityPlan INSTANCE = new ArrayMutabilityPlan(); @SuppressWarnings({ "unchecked", "SuspiciousSystemArraycopy" }) + @AllowReflection public T deepCopyNotNull(T value) { if ( ! value.getClass().isArray() ) { // ugh! cannot find a way to properly define the type signature here diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanPrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanPrimitiveArrayJavaType.java index 2d6b4e07f889..a7ad513fdc57 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanPrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanPrimitiveArrayJavaType.java @@ -16,6 +16,7 @@ import org.hibernate.SharedSessionContract; import org.hibernate.engine.jdbc.BinaryStream; import org.hibernate.engine.jdbc.internal.ArrayBackedBinaryStream; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.internal.util.SerializationHelper; import org.hibernate.type.descriptor.WrapperOptions; @@ -24,6 +25,7 @@ * * @author Christian Beikov */ +@AllowReflection // Needed for arbitrary array wrapping/unwrapping public class BooleanPrimitiveArrayJavaType extends AbstractArrayJavaType { public static final BooleanPrimitiveArrayJavaType INSTANCE = new BooleanPrimitiveArrayJavaType(); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoublePrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoublePrimitiveArrayJavaType.java index c598d009dbf6..f29c53fe8241 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoublePrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoublePrimitiveArrayJavaType.java @@ -16,6 +16,7 @@ import org.hibernate.SharedSessionContract; import org.hibernate.engine.jdbc.BinaryStream; import org.hibernate.engine.jdbc.internal.ArrayBackedBinaryStream; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.internal.util.SerializationHelper; import org.hibernate.type.descriptor.WrapperOptions; @@ -24,6 +25,7 @@ * * @author Christian Beikov */ +@AllowReflection // Needed for arbitrary array wrapping/unwrapping public class DoublePrimitiveArrayJavaType extends AbstractArrayJavaType { public static final DoublePrimitiveArrayJavaType INSTANCE = new DoublePrimitiveArrayJavaType(); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatPrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatPrimitiveArrayJavaType.java index 442c09c387f2..db097bc95599 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatPrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatPrimitiveArrayJavaType.java @@ -16,6 +16,7 @@ import org.hibernate.SharedSessionContract; import org.hibernate.engine.jdbc.BinaryStream; import org.hibernate.engine.jdbc.internal.ArrayBackedBinaryStream; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.internal.util.SerializationHelper; import org.hibernate.type.descriptor.WrapperOptions; @@ -24,6 +25,7 @@ * * @author Christian Beikov */ +@AllowReflection // Needed for arbitrary array wrapping/unwrapping public class FloatPrimitiveArrayJavaType extends AbstractArrayJavaType { public static final FloatPrimitiveArrayJavaType INSTANCE = new FloatPrimitiveArrayJavaType(); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerPrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerPrimitiveArrayJavaType.java index 60edc5ebe8f4..3dc831ee2b05 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerPrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerPrimitiveArrayJavaType.java @@ -16,6 +16,7 @@ import org.hibernate.SharedSessionContract; import org.hibernate.engine.jdbc.BinaryStream; import org.hibernate.engine.jdbc.internal.ArrayBackedBinaryStream; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.internal.util.SerializationHelper; import org.hibernate.type.descriptor.WrapperOptions; @@ -24,6 +25,7 @@ * * @author Christian Beikov */ +@AllowReflection // Needed for arbitrary array wrapping/unwrapping public class IntegerPrimitiveArrayJavaType extends AbstractArrayJavaType { public static final IntegerPrimitiveArrayJavaType INSTANCE = new IntegerPrimitiveArrayJavaType(); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongPrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongPrimitiveArrayJavaType.java index d4423f9c0f4a..5369978dca61 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongPrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongPrimitiveArrayJavaType.java @@ -16,6 +16,7 @@ import org.hibernate.SharedSessionContract; import org.hibernate.engine.jdbc.BinaryStream; import org.hibernate.engine.jdbc.internal.ArrayBackedBinaryStream; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.internal.util.SerializationHelper; import org.hibernate.type.descriptor.WrapperOptions; @@ -24,6 +25,7 @@ * * @author Christian Beikov */ +@AllowReflection // Needed for arbitrary array wrapping/unwrapping public class LongPrimitiveArrayJavaType extends AbstractArrayJavaType { public static final LongPrimitiveArrayJavaType INSTANCE = new LongPrimitiveArrayJavaType(); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortPrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortPrimitiveArrayJavaType.java index d0bf0b6731bc..981cfd87df0f 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortPrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortPrimitiveArrayJavaType.java @@ -16,6 +16,7 @@ import org.hibernate.SharedSessionContract; import org.hibernate.engine.jdbc.BinaryStream; import org.hibernate.engine.jdbc.internal.ArrayBackedBinaryStream; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.internal.util.SerializationHelper; import org.hibernate.type.descriptor.WrapperOptions; @@ -24,6 +25,7 @@ * * @author Christian Beikov */ +@AllowReflection // Needed for arbitrary array wrapping/unwrapping public class ShortPrimitiveArrayJavaType extends AbstractArrayJavaType { public static final ShortPrimitiveArrayJavaType INSTANCE = new ShortPrimitiveArrayJavaType(); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java index 88e32b23bd41..cbdef1177c54 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java @@ -21,6 +21,7 @@ import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.BinaryStream; import org.hibernate.engine.jdbc.internal.ArrayBackedBinaryStream; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.internal.util.SerializationHelper; import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.metamodel.CollectionClassification; @@ -46,6 +47,7 @@ * @author Christian Beikov */ @Incubating +@AllowReflection // Needed for arbitrary array wrapping/unwrapping public class BasicCollectionJavaType, E> extends AbstractJavaType implements BasicPluralJavaType { diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java index 3bf37b59fb28..7581cf78625b 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java @@ -17,6 +17,7 @@ import org.hibernate.dialect.StructHelper; import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.type.BasicPluralType; import org.hibernate.type.descriptor.ValueBinder; @@ -40,6 +41,7 @@ * @author Christian Beikov * @author Jordan Gigov */ +@AllowReflection // See https://hibernate.atlassian.net/browse/HHH-16809 public class ArrayJdbcType implements JdbcType { private final JdbcType elementJdbcType; diff --git a/hibernate-core/src/main/java/org/hibernate/type/format/jaxb/JaxbXmlFormatMapper.java b/hibernate-core/src/main/java/org/hibernate/type/format/jaxb/JaxbXmlFormatMapper.java index cb567855cdcb..6a5becf99558 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/format/jaxb/JaxbXmlFormatMapper.java +++ b/hibernate-core/src/main/java/org/hibernate/type/format/jaxb/JaxbXmlFormatMapper.java @@ -20,6 +20,7 @@ import jakarta.xml.bind.annotation.XmlElement; import org.hibernate.dialect.XmlHelper; +import org.hibernate.internal.build.AllowReflection; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.sql.ast.spi.StringBuilderSqlAppender; @@ -70,6 +71,7 @@ public JaxbXmlFormatMapper(boolean legacyFormat) { } @Override + @AllowReflection public T fromString(CharSequence charSequence, JavaType javaType, WrapperOptions wrapperOptions) { if ( javaType.getJavaType() == String.class || javaType.getJavaType() == Object.class ) { return (T) charSequence.toString(); diff --git a/local-build-plugins/src/main/groovy/local.code-quality.gradle b/local-build-plugins/src/main/groovy/local.code-quality.gradle index 66308b2978e6..4b41bb60a14d 100644 --- a/local-build-plugins/src/main/groovy/local.code-quality.gradle +++ b/local-build-plugins/src/main/groovy/local.code-quality.gradle @@ -123,10 +123,14 @@ tasks.forbiddenApisMain { //bundledSignatures += ["jdk-system-out", "jdk-non-portable", "jdk-unsafe-${jdkVersions.baseline}"] bundledSignatures += ["jdk-system-out", "jdk-non-portable"] + signaturesFiles += rootProject.files('rules/forbidden-apis.txt') + ignoreSignaturesOfMissingClasses = true + suppressAnnotations += [ "org.hibernate.internal.build.AllowSysOut", "org.hibernate.internal.build.AllowPrintStacktrace", - "org.hibernate.internal.build.AllowNonPortable" + "org.hibernate.internal.build.AllowNonPortable", + "org.hibernate.internal.build.AllowReflection" ] } diff --git a/rules/forbidden-apis.txt b/rules/forbidden-apis.txt new file mode 100644 index 000000000000..01007e7b26c1 --- /dev/null +++ b/rules/forbidden-apis.txt @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# Copyright Red Hat Inc. and Hibernate Authors + +# This file is a list of signatures to feed into Forbidden-API. +# It defines classes/methods to be avoided. +# See here for the syntax of this file: https://github.com/policeman-tools/forbidden-apis/wiki/SignaturesSyntax + +################################################################################################################ +# Reflection-related +@defaultMessage Use 'new Object[]' instead if possible. This forbidden method requires reflection and may not work in natively compiled applications. If you really must use this forbidden method, annotate the calling method with @AllowReflection. + +java.lang.reflect.Array#newInstance(java.lang.Class, int) +java.lang.reflect.Array#newInstance(java.lang.Class, int[]) +org.hibernate.internal.util.collections.ArrayHelper#newInstance(java.lang.Class, int) +org.hibernate.internal.util.collections.ArrayHelper#filledArray(java.lang.Object, java.lang.Class, int) +org.hibernate.internal.util.collections.ArrayHelper#join(java.lang.Object[], java.lang.Object[]) + +################################################################################################################ +# Misc -- put things here as a last resort, but if possible prefer adding a category above with an actionable message. +@defaultMessage Should not be used. \ No newline at end of file From fe2fe30836b45ec17ebf9131d777bbe4d0e01369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Thu, 2 Jan 2025 14:47:31 +0100 Subject: [PATCH 02/11] HHH-18976 Deprecate ArrayHelper#newInstance in favor of the standard Array#newInstance --- .../org/hibernate/internal/util/collections/ArrayHelper.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java index 556792813a32..7b7e5a940441 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java @@ -522,6 +522,10 @@ public static void forEach(T[] array, Consumer consumer) { } } + /** + * @deprecated Use {@link Array#newInstance(Class, int)} instead. + */ + @Deprecated @SuppressWarnings("unchecked") @AllowReflection public static T[] newInstance(Class elementType, int length) { From 5025c2b8133fb333a3f8d735cd672f5f18f23a3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Fri, 3 Jan 2025 13:46:30 +0100 Subject: [PATCH 03/11] HHH-18976 Use a clone-based implementation for all array mutability plans It's more consistent, and happens to get rid of ArrayMutabilityPlan, which involved an unnecessary use of Array.newInstance. I've also seen claims that clone() performs better than Array.newInstance() due to not having to zero-out the allocated memory, but I doubt that's relevant here. --- .../descriptor/java/ArrayMutabilityPlan.java | 5 ++++ .../java/BooleanPrimitiveArrayJavaType.java | 25 +++--------------- .../descriptor/java/ByteArrayJavaType.java | 2 +- .../java/CharacterArrayJavaType.java | 2 +- .../java/DoublePrimitiveArrayJavaType.java | 25 +++--------------- .../java/FloatPrimitiveArrayJavaType.java | 25 +++--------------- .../ImmutableObjectArrayMutabilityPlan.java | 26 +++++++++++++++++++ .../java/IntegerPrimitiveArrayJavaType.java | 25 +++--------------- .../java/LongPrimitiveArrayJavaType.java | 25 +++--------------- .../java/PrimitiveByteArrayJavaType.java | 10 +++++-- .../java/PrimitiveCharacterArrayJavaType.java | 9 ++++++- .../java/ShortPrimitiveArrayJavaType.java | 25 +++--------------- 12 files changed, 67 insertions(+), 137 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ImmutableObjectArrayMutabilityPlan.java diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayMutabilityPlan.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayMutabilityPlan.java index 892aaca02963..de058dfbb2e8 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayMutabilityPlan.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ArrayMutabilityPlan.java @@ -12,7 +12,12 @@ * are immutable, a shallow copy is enough. * * @author Steve Ebersole + * + * @deprecated Use {@link ImmutableObjectArrayMutabilityPlan#get()} for object arrays, + * or implement a dedicated mutability plan for primitive arrays + * (see for example {@link ShortPrimitiveArrayJavaType}'s mutability plan). */ +@Deprecated public class ArrayMutabilityPlan extends MutableMutabilityPlan { public static final ArrayMutabilityPlan INSTANCE = new ArrayMutabilityPlan(); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanPrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanPrimitiveArrayJavaType.java index a7ad513fdc57..44c59dec3324 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanPrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanPrimitiveArrayJavaType.java @@ -4,7 +4,6 @@ */ package org.hibernate.type.descriptor.java; -import java.io.Serializable; import java.lang.reflect.Array; import java.sql.SQLException; import java.util.ArrayList; @@ -13,7 +12,6 @@ import java.util.List; import org.hibernate.HibernateException; -import org.hibernate.SharedSessionContract; import org.hibernate.engine.jdbc.BinaryStream; import org.hibernate.engine.jdbc.internal.ArrayBackedBinaryStream; import org.hibernate.internal.build.AllowReflection; @@ -185,27 +183,10 @@ else if ( value instanceof Collection collection ) { throw unknownWrap( value.getClass() ); } - private static class ArrayMutabilityPlan implements MutabilityPlan { - - @Override - public boolean isMutable() { - return true; - } - + private static class ArrayMutabilityPlan extends MutableMutabilityPlan { @Override - public boolean[] deepCopy(boolean[] value) { - return value == null ? null : value.clone(); + protected boolean[] deepCopyNotNull(boolean[] value) { + return value.clone(); } - - @Override - public Serializable disassemble(boolean[] value, SharedSessionContract session) { - return deepCopy( value ); - } - - @Override - public boolean[] assemble(Serializable cached, SharedSessionContract session) { - return deepCopy( (boolean[]) cached ); - } - } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ByteArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ByteArrayJavaType.java index 8c2cef146ed7..45d97ee7f112 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ByteArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ByteArrayJavaType.java @@ -30,7 +30,7 @@ public class ByteArrayJavaType extends AbstractClassJavaType { @SuppressWarnings("unchecked") public ByteArrayJavaType() { - super( Byte[].class, ArrayMutabilityPlan.INSTANCE, IncomparableComparator.INSTANCE ); + super( Byte[].class, ImmutableObjectArrayMutabilityPlan.get(), IncomparableComparator.INSTANCE ); } @Override public boolean areEqual(Byte[] one, Byte[] another) { diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CharacterArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CharacterArrayJavaType.java index ecdea5ef9da4..f21d020b65fb 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CharacterArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CharacterArrayJavaType.java @@ -29,7 +29,7 @@ public class CharacterArrayJavaType extends AbstractClassJavaType { @SuppressWarnings("unchecked") public CharacterArrayJavaType() { - super( Character[].class, ArrayMutabilityPlan.INSTANCE, IncomparableComparator.INSTANCE ); + super( Character[].class, ImmutableObjectArrayMutabilityPlan.get(), IncomparableComparator.INSTANCE ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoublePrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoublePrimitiveArrayJavaType.java index f29c53fe8241..e0418b58031b 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoublePrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoublePrimitiveArrayJavaType.java @@ -4,7 +4,6 @@ */ package org.hibernate.type.descriptor.java; -import java.io.Serializable; import java.lang.reflect.Array; import java.sql.SQLException; import java.util.ArrayList; @@ -13,7 +12,6 @@ import java.util.List; import org.hibernate.HibernateException; -import org.hibernate.SharedSessionContract; import org.hibernate.engine.jdbc.BinaryStream; import org.hibernate.engine.jdbc.internal.ArrayBackedBinaryStream; import org.hibernate.internal.build.AllowReflection; @@ -185,27 +183,10 @@ else if ( value instanceof Collection collection ) { throw unknownWrap( value.getClass() ); } - private static class ArrayMutabilityPlan implements MutabilityPlan { - - @Override - public boolean isMutable() { - return true; - } - + private static class ArrayMutabilityPlan extends MutableMutabilityPlan { @Override - public double[] deepCopy(double[] value) { - return value == null ? null : value.clone(); + protected double[] deepCopyNotNull(double[] value) { + return value.clone(); } - - @Override - public Serializable disassemble(double[] value, SharedSessionContract session) { - return deepCopy( value ); - } - - @Override - public double[] assemble(Serializable cached, SharedSessionContract session) { - return deepCopy( (double[]) cached ); - } - } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatPrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatPrimitiveArrayJavaType.java index db097bc95599..457b65c3bcf8 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatPrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatPrimitiveArrayJavaType.java @@ -4,7 +4,6 @@ */ package org.hibernate.type.descriptor.java; -import java.io.Serializable; import java.lang.reflect.Array; import java.sql.SQLException; import java.util.ArrayList; @@ -13,7 +12,6 @@ import java.util.List; import org.hibernate.HibernateException; -import org.hibernate.SharedSessionContract; import org.hibernate.engine.jdbc.BinaryStream; import org.hibernate.engine.jdbc.internal.ArrayBackedBinaryStream; import org.hibernate.internal.build.AllowReflection; @@ -185,27 +183,10 @@ else if ( value instanceof Collection collection ) { throw unknownWrap( value.getClass() ); } - private static class ArrayMutabilityPlan implements MutabilityPlan { - - @Override - public boolean isMutable() { - return true; - } - + private static class ArrayMutabilityPlan extends MutableMutabilityPlan { @Override - public float[] deepCopy(float[] value) { - return value == null ? null : value.clone(); + protected float[] deepCopyNotNull(float[] value) { + return value.clone(); } - - @Override - public Serializable disassemble(float[] value, SharedSessionContract session) { - return deepCopy( value ); - } - - @Override - public float[] assemble(Serializable cached, SharedSessionContract session) { - return deepCopy( (float[]) cached ); - } - } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ImmutableObjectArrayMutabilityPlan.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ImmutableObjectArrayMutabilityPlan.java new file mode 100644 index 000000000000..dfde02f1dd36 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ImmutableObjectArrayMutabilityPlan.java @@ -0,0 +1,26 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.type.descriptor.java; + +/** + * A mutability plan for mutable arrays of immutable, non-primitive objects. + *

+ * Since the elements themselves are immutable, the deep copy can be implemented with a shallow copy. + * + * @author Steve Ebersole + */ +public final class ImmutableObjectArrayMutabilityPlan extends MutableMutabilityPlan { + @SuppressWarnings("rawtypes") + private static final ImmutableObjectArrayMutabilityPlan INSTANCE = new ImmutableObjectArrayMutabilityPlan(); + + @SuppressWarnings("unchecked") // Works for any T + public static ImmutableObjectArrayMutabilityPlan get() { + return (ImmutableObjectArrayMutabilityPlan) INSTANCE; + } + + public T[] deepCopyNotNull(T[] value) { + return value.clone(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerPrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerPrimitiveArrayJavaType.java index 3dc831ee2b05..561db537ce57 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerPrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerPrimitiveArrayJavaType.java @@ -4,7 +4,6 @@ */ package org.hibernate.type.descriptor.java; -import java.io.Serializable; import java.lang.reflect.Array; import java.sql.SQLException; import java.util.ArrayList; @@ -13,7 +12,6 @@ import java.util.List; import org.hibernate.HibernateException; -import org.hibernate.SharedSessionContract; import org.hibernate.engine.jdbc.BinaryStream; import org.hibernate.engine.jdbc.internal.ArrayBackedBinaryStream; import org.hibernate.internal.build.AllowReflection; @@ -185,27 +183,10 @@ else if ( value instanceof Collection collection ) { throw unknownWrap( value.getClass() ); } - private static class ArrayMutabilityPlan implements MutabilityPlan { - - @Override - public boolean isMutable() { - return true; - } - + private static class ArrayMutabilityPlan extends MutableMutabilityPlan { @Override - public int[] deepCopy(int[] value) { - return value == null ? null : value.clone(); + protected int[] deepCopyNotNull(int[] value) { + return value.clone(); } - - @Override - public Serializable disassemble(int[] value, SharedSessionContract session) { - return deepCopy( value ); - } - - @Override - public int[] assemble(Serializable cached, SharedSessionContract session) { - return deepCopy( (int[]) cached ); - } - } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongPrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongPrimitiveArrayJavaType.java index 5369978dca61..d70f37375e9a 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongPrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongPrimitiveArrayJavaType.java @@ -4,7 +4,6 @@ */ package org.hibernate.type.descriptor.java; -import java.io.Serializable; import java.lang.reflect.Array; import java.sql.SQLException; import java.util.ArrayList; @@ -13,7 +12,6 @@ import java.util.List; import org.hibernate.HibernateException; -import org.hibernate.SharedSessionContract; import org.hibernate.engine.jdbc.BinaryStream; import org.hibernate.engine.jdbc.internal.ArrayBackedBinaryStream; import org.hibernate.internal.build.AllowReflection; @@ -185,27 +183,10 @@ else if ( value instanceof Collection collection ) { throw unknownWrap( value.getClass() ); } - private static class ArrayMutabilityPlan implements MutabilityPlan { - - @Override - public boolean isMutable() { - return true; - } - + private static class ArrayMutabilityPlan extends MutableMutabilityPlan { @Override - public long[] deepCopy(long[] value) { - return value == null ? null : value.clone(); + protected long[] deepCopyNotNull(long[] value) { + return value.clone(); } - - @Override - public Serializable disassemble(long[] value, SharedSessionContract session) { - return deepCopy( value ); - } - - @Override - public long[] assemble(Serializable cached, SharedSessionContract session) { - return deepCopy( (long[]) cached ); - } - } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveByteArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveByteArrayJavaType.java index c323ae1b1573..d7ce8279b1ff 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveByteArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveByteArrayJavaType.java @@ -28,9 +28,8 @@ public class PrimitiveByteArrayJavaType extends AbstractClassJavaType implements VersionJavaType { public static final PrimitiveByteArrayJavaType INSTANCE = new PrimitiveByteArrayJavaType(); - @SuppressWarnings("unchecked") public PrimitiveByteArrayJavaType() { - super( byte[].class, ArrayMutabilityPlan.INSTANCE, RowVersionComparator.INSTANCE ); + super( byte[].class, new ArrayMutabilityPlan(), RowVersionComparator.INSTANCE ); } @Override @@ -160,4 +159,11 @@ public byte[] next( Integer scale, SharedSessionContractImplementor session) { return current; } + + private static class ArrayMutabilityPlan extends MutableMutabilityPlan { + @Override + protected byte[] deepCopyNotNull(byte[] value) { + return value.clone(); + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveCharacterArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveCharacterArrayJavaType.java index f44d1aab3033..ae79529b8f1d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveCharacterArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveCharacterArrayJavaType.java @@ -24,7 +24,7 @@ public class PrimitiveCharacterArrayJavaType extends AbstractClassJavaType char[] coerce(X value, CoercionContext coercionContext) { return wrap( value, null ); } + + private static class ArrayMutabilityPlan extends MutableMutabilityPlan { + @Override + protected char[] deepCopyNotNull(char[] value) { + return value.clone(); + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortPrimitiveArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortPrimitiveArrayJavaType.java index 981cfd87df0f..f4615d39d8d2 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortPrimitiveArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortPrimitiveArrayJavaType.java @@ -4,7 +4,6 @@ */ package org.hibernate.type.descriptor.java; -import java.io.Serializable; import java.lang.reflect.Array; import java.sql.SQLException; import java.util.ArrayList; @@ -13,7 +12,6 @@ import java.util.List; import org.hibernate.HibernateException; -import org.hibernate.SharedSessionContract; import org.hibernate.engine.jdbc.BinaryStream; import org.hibernate.engine.jdbc.internal.ArrayBackedBinaryStream; import org.hibernate.internal.build.AllowReflection; @@ -185,27 +183,10 @@ else if ( value instanceof Collection collection ) { throw unknownWrap( value.getClass() ); } - private static class ArrayMutabilityPlan implements MutabilityPlan { - - @Override - public boolean isMutable() { - return true; - } - + private static class ArrayMutabilityPlan extends MutableMutabilityPlan { @Override - public short[] deepCopy(short[] value) { - return value == null ? null : value.clone(); + protected short[] deepCopyNotNull(short[] value) { + return value.clone(); } - - @Override - public Serializable disassemble(short[] value, SharedSessionContract session) { - return deepCopy( value ); - } - - @Override - public short[] assemble(Serializable cached, SharedSessionContract session) { - return deepCopy( (short[]) cached ); - } - } } From 2238c6629be6c02c6541d04a34f098fc2f65094f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Fri, 3 Jan 2025 15:18:04 +0100 Subject: [PATCH 04/11] HHH-18976 Simplify MultiKeyLoadHelper#resolveArrayJdbcMapping No functional impact, it's just less redundant. --- .../loader/ast/internal/CollectionBatchLoaderArrayParam.java | 5 ----- .../loader/ast/internal/EntityBatchLoaderArrayParam.java | 1 - .../loader/ast/internal/MultiIdEntityLoaderArrayParam.java | 1 - .../hibernate/loader/ast/internal/MultiKeyLoadHelper.java | 3 ++- .../loader/ast/internal/MultiNaturalIdLoaderArrayParam.java | 5 ----- 5 files changed, 2 insertions(+), 13 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderArrayParam.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderArrayParam.java index 029dcd38671e..24878a20b6be 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderArrayParam.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderArrayParam.java @@ -32,7 +32,6 @@ import org.hibernate.sql.exec.spi.JdbcParametersList; import org.hibernate.sql.results.internal.RowTransformerStandardImpl; import org.hibernate.sql.results.spi.ListResultsConsumer; -import org.hibernate.type.BasicType; import static org.hibernate.loader.ast.internal.MultiKeyLoadHelper.hasSingleId; import static org.hibernate.loader.ast.internal.MultiKeyLoadHelper.trimIdBatch; @@ -74,11 +73,7 @@ public CollectionBatchLoaderArrayParam( .getClass(); keyDomainType = getKeyType( keyDescriptor.getKeyPart() ); - final BasicType arrayBasicType = getSessionFactory().getTypeConfiguration() - .getBasicTypeRegistry() - .getRegisteredType( jdbcArrayClass ); arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping( - arrayBasicType, jdbcMapping, jdbcArrayClass, getSessionFactory() diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/EntityBatchLoaderArrayParam.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/EntityBatchLoaderArrayParam.java index 3a5213eb19fb..4289c88bb1d0 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/EntityBatchLoaderArrayParam.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/EntityBatchLoaderArrayParam.java @@ -80,7 +80,6 @@ public EntityBatchLoaderArrayParam( final Class arrayClass = Array.newInstance( identifierMapping.getJavaType().getJavaTypeClass(), 0 ).getClass(); arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping( - sessionFactory.getTypeConfiguration().getBasicTypeRegistry().getRegisteredType( arrayClass ), identifierMapping.getJdbcMapping(), arrayClass, sessionFactory diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdEntityLoaderArrayParam.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdEntityLoaderArrayParam.java index 66724a8ab7f2..d6bb4dbada17 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdEntityLoaderArrayParam.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdEntityLoaderArrayParam.java @@ -51,7 +51,6 @@ public MultiIdEntityLoaderArrayParam( super( entityDescriptor, sessionFactory ); final Class idArrayClass = idArray.getClass(); arrayJdbcMapping = resolveArrayJdbcMapping( - getSessionFactory().getTypeConfiguration().getBasicTypeRegistry().getRegisteredType( idArrayClass ), getIdentifierMapping().getJdbcMapping(), idArrayClass, getSessionFactory() diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiKeyLoadHelper.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiKeyLoadHelper.java index 87e4bd6b451b..680158497dec 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiKeyLoadHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiKeyLoadHelper.java @@ -27,10 +27,11 @@ public static boolean supportsSqlArrayType(Dialect dialect) { } public static JdbcMapping resolveArrayJdbcMapping( - BasicType arrayBasicType, JdbcMapping keyMapping, Class arrayClass, SessionFactoryImplementor sessionFactory) { + BasicType arrayBasicType = sessionFactory.getTypeConfiguration().getBasicTypeRegistry() + .getRegisteredType( arrayClass ); if ( arrayBasicType != null ) { return arrayBasicType; } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderArrayParam.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderArrayParam.java index a4a0d92dc0ff..46ae21542f2c 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderArrayParam.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderArrayParam.java @@ -23,8 +23,6 @@ import org.hibernate.sql.exec.internal.JdbcParameterImpl; import org.hibernate.sql.exec.spi.JdbcOperationQuerySelect; import org.hibernate.sql.exec.spi.JdbcParameterBindings; -import org.hibernate.type.BasicType; -import org.hibernate.type.BasicTypeRegistry; /** * Standard MultiNaturalIdLoader implementation @@ -77,10 +75,7 @@ public List multiLoad(K[] naturalIds, MultiNaturalIdLoadOptions loadOptio ? LockOptions.NONE : loadOptions.getLockOptions(); - final BasicTypeRegistry basicTypeRegistry = sessionFactory.getTypeConfiguration().getBasicTypeRegistry(); - final BasicType arrayBasicType = basicTypeRegistry.getRegisteredType( keyArrayClass ); final JdbcMapping arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping( - arrayBasicType, getNaturalIdMapping().getSingleJdbcMapping(), keyArrayClass, sessionFactory From cb6c084e76eb94e0e02e57fd753b0a3f148bc6b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Fri, 3 Jan 2025 14:52:15 +0100 Subject: [PATCH 05/11] HHH-18976 Get rid of dynamic array instantiations used only to resolve type descriptors --- .../CollectionBatchLoaderArrayParam.java | 6 +- .../internal/EntityBatchLoaderArrayParam.java | 6 +- .../MultiIdEntityLoaderArrayParam.java | 4 +- .../ast/internal/MultiKeyLoadHelper.java | 10 +-- .../MultiNaturalIdLoaderArrayParam.java | 7 +- .../org/hibernate/type/BasicTypeRegistry.java | 4 + .../descriptor/java/spi/JavaTypeRegistry.java | 88 +++++++++++-------- 7 files changed, 67 insertions(+), 58 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderArrayParam.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderArrayParam.java index 24878a20b6be..e0882da3efd8 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderArrayParam.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderArrayParam.java @@ -51,7 +51,6 @@ public class CollectionBatchLoaderArrayParam private final SelectStatement sqlSelect; private final JdbcOperationQuerySelect jdbcSelectOperation; - @AllowReflection public CollectionBatchLoaderArrayParam( int domainBatchSize, LoadQueryInfluencers loadQueryInfluencers, @@ -69,13 +68,12 @@ public CollectionBatchLoaderArrayParam( final ForeignKeyDescriptor keyDescriptor = getLoadable().getKeyDescriptor(); final JdbcMapping jdbcMapping = keyDescriptor.getSingleJdbcMapping(); - final Class jdbcArrayClass = Array.newInstance( jdbcMapping.getJdbcJavaType().getJavaTypeClass(), 0 ) - .getClass(); + final Class jdbcJavaTypeClass = jdbcMapping.getJdbcJavaType().getJavaTypeClass(); keyDomainType = getKeyType( keyDescriptor.getKeyPart() ); arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping( jdbcMapping, - jdbcArrayClass, + jdbcJavaTypeClass, getSessionFactory() ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/EntityBatchLoaderArrayParam.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/EntityBatchLoaderArrayParam.java index 4289c88bb1d0..40dfc5839736 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/EntityBatchLoaderArrayParam.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/EntityBatchLoaderArrayParam.java @@ -59,7 +59,6 @@ public class EntityBatchLoaderArrayParam * {@link EntityIdentifierMapping} is not available at that time. On first use, we know we * have it available */ - @AllowReflection public EntityBatchLoaderArrayParam( int domainBatchSize, EntityMappingType entityDescriptor, @@ -77,11 +76,10 @@ public EntityBatchLoaderArrayParam( } identifierMapping = (BasicEntityIdentifierMapping) getLoadable().getIdentifierMapping(); - final Class arrayClass = - Array.newInstance( identifierMapping.getJavaType().getJavaTypeClass(), 0 ).getClass(); + final Class idClass = identifierMapping.getJavaType().getJavaTypeClass(); arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping( identifierMapping.getJdbcMapping(), - arrayClass, + idClass, sessionFactory ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdEntityLoaderArrayParam.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdEntityLoaderArrayParam.java index d6bb4dbada17..86a40d030da6 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdEntityLoaderArrayParam.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdEntityLoaderArrayParam.java @@ -49,10 +49,10 @@ public MultiIdEntityLoaderArrayParam( EntityMappingType entityDescriptor, SessionFactoryImplementor sessionFactory) { super( entityDescriptor, sessionFactory ); - final Class idArrayClass = idArray.getClass(); + final Class idClass = idArray.getClass().getComponentType(); arrayJdbcMapping = resolveArrayJdbcMapping( getIdentifierMapping().getJdbcMapping(), - idArrayClass, + idClass, getSessionFactory() ); jdbcParameter = new JdbcParameterImpl( arrayJdbcMapping ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiKeyLoadHelper.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiKeyLoadHelper.java index 680158497dec..424578ba8083 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiKeyLoadHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiKeyLoadHelper.java @@ -28,10 +28,10 @@ public static boolean supportsSqlArrayType(Dialect dialect) { public static JdbcMapping resolveArrayJdbcMapping( JdbcMapping keyMapping, - Class arrayClass, + Class elementClass, SessionFactoryImplementor sessionFactory) { BasicType arrayBasicType = sessionFactory.getTypeConfiguration().getBasicTypeRegistry() - .getRegisteredType( arrayClass ); + .getRegisteredArrayType( elementClass ); if ( arrayBasicType != null ) { return arrayBasicType; } @@ -39,9 +39,9 @@ public static JdbcMapping resolveArrayJdbcMapping( final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration(); final JavaTypeRegistry javaTypeRegistry = typeConfiguration.getJavaTypeRegistry(); - final JavaType rawArrayJavaType = javaTypeRegistry.resolveDescriptor( arrayClass ); - if ( !(rawArrayJavaType instanceof BasicPluralJavaType arrayJavaType) ) { - throw new IllegalArgumentException( "Expecting BasicPluralJavaType for array class `" + arrayClass.getName() + "`, but got `" + rawArrayJavaType + "`" ); + final JavaType rawArrayJavaType = javaTypeRegistry.resolveArrayDescriptor( elementClass ); + if ( !(rawArrayJavaType instanceof BasicPluralJavaType arrayJavaType ) ) { + throw new IllegalArgumentException( "Expecting BasicPluralJavaType for array class `" + elementClass.getTypeName() + "[]`, but got `" + rawArrayJavaType + "`" ); } //noinspection unchecked,rawtypes diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderArrayParam.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderArrayParam.java index 46ae21542f2c..dad4597ecdb6 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderArrayParam.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderArrayParam.java @@ -29,15 +29,14 @@ */ public class MultiNaturalIdLoaderArrayParam implements MultiNaturalIdLoader, SqlArrayMultiKeyLoader { private final EntityMappingType entityDescriptor; - private final Class keyArrayClass; + private final Class keyClass; public MultiNaturalIdLoaderArrayParam(EntityMappingType entityDescriptor) { assert entityDescriptor.getNaturalIdMapping() instanceof SimpleNaturalIdMapping; this.entityDescriptor = entityDescriptor; - final Class keyClass = entityDescriptor.getNaturalIdMapping().getJavaType().getJavaTypeClass(); - this.keyArrayClass = LoaderHelper.createTypedArray( keyClass, 0 ).getClass(); + this.keyClass = entityDescriptor.getNaturalIdMapping().getJavaType().getJavaTypeClass(); } @Override @@ -77,7 +76,7 @@ public List multiLoad(K[] naturalIds, MultiNaturalIdLoadOptions loadOptio final JdbcMapping arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping( getNaturalIdMapping().getSingleJdbcMapping(), - keyArrayClass, + keyClass, sessionFactory ); final JdbcParameter jdbcParameter = new JdbcParameterImpl( arrayJdbcMapping ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/BasicTypeRegistry.java b/hibernate-core/src/main/java/org/hibernate/type/BasicTypeRegistry.java index c6f7c197bb09..97354c3f813f 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/BasicTypeRegistry.java +++ b/hibernate-core/src/main/java/org/hibernate/type/BasicTypeRegistry.java @@ -117,6 +117,10 @@ public BasicType getRegisteredType(Class javaType) { return getRegisteredType( javaType.getTypeName() ); } + public BasicType getRegisteredArrayType(java.lang.reflect.Type javaElementType) { + return getRegisteredType( javaElementType.getTypeName() + "[]" ); + } + public BasicType resolve(BasicTypeReference basicTypeReference) { return getRegisteredType( basicTypeReference.getName() ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeRegistry.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeRegistry.java index c54b21539503..725f876cb24d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeRegistry.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeRegistry.java @@ -34,7 +34,7 @@ public class JavaTypeRegistry implements JavaTypeBaseline.BaselineTarget, Serial private static final Logger log = Logger.getLogger( JavaTypeRegistry.class ); private final TypeConfiguration typeConfiguration; - private final ConcurrentHashMap> descriptorsByType = new ConcurrentHashMap<>(); + private final ConcurrentHashMap> descriptorsByTypeName = new ConcurrentHashMap<>(); public JavaTypeRegistry(TypeConfiguration typeConfiguration) { this.typeConfiguration = typeConfiguration; @@ -56,7 +56,7 @@ public void addBaselineDescriptor(JavaType descriptor) { @Override public void addBaselineDescriptor(Type describedJavaType, JavaType descriptor) { performInjections( descriptor ); - descriptorsByType.put( describedJavaType, descriptor ); + descriptorsByTypeName.put( describedJavaType.getTypeName(), descriptor ); } private void performInjections(JavaType descriptor) { @@ -71,7 +71,7 @@ private void performInjections(JavaType descriptor) { // descriptor access public void forEachDescriptor(Consumer> consumer) { - descriptorsByType.values().forEach( consumer ); + descriptorsByTypeName.values().forEach( consumer ); } public JavaType getDescriptor(Type javaType) { @@ -79,7 +79,7 @@ public JavaType getDescriptor(Type javaType) { } public void addDescriptor(JavaType descriptor) { - JavaType old = descriptorsByType.put( descriptor.getJavaType(), descriptor ); + JavaType old = descriptorsByTypeName.put( descriptor.getJavaType().getTypeName(), descriptor ); if ( old != null ) { log.debugf( "JavaTypeRegistry entry replaced : %s -> %s (was %s)", @@ -93,40 +93,51 @@ public void addDescriptor(JavaType descriptor) { public JavaType findDescriptor(Type javaType) { //noinspection unchecked - return (JavaType) descriptorsByType.get( javaType ); + return (JavaType) descriptorsByTypeName.get( javaType.getTypeName() ); } public JavaType resolveDescriptor(Type javaType, Supplier> creator) { - final JavaType cached = descriptorsByType.get( javaType ); + return resolveDescriptor( javaType.getTypeName(), creator ); + } + + private JavaType resolveDescriptor(String javaTypeName, Supplier> creator) { + final JavaType cached = descriptorsByTypeName.get( javaTypeName ); if ( cached != null ) { //noinspection unchecked return (JavaType) cached; } final JavaType created = creator.get(); - descriptorsByType.put( javaType, created ); + descriptorsByTypeName.put( javaTypeName, created ); return created; } public JavaType resolveDescriptor(Type javaType) { - return resolveDescriptor( javaType, (elementJavaType, typeConfiguration) -> { - final MutabilityPlan determinedPlan = RegistryHelper.INSTANCE.determineMutabilityPlan( - elementJavaType, - typeConfiguration - ); - if ( determinedPlan != null ) { - return determinedPlan; - } + return resolveDescriptor( javaType, JavaTypeRegistry::createMutabilityPlan ); + } + + private static MutabilityPlan createMutabilityPlan(Type elementJavaType, TypeConfiguration typeConfiguration) { + final MutabilityPlan determinedPlan = RegistryHelper.INSTANCE.determineMutabilityPlan( + elementJavaType, + typeConfiguration + ); + if ( determinedPlan != null ) { + return determinedPlan; + } + + return MutableMutabilityPlan.INSTANCE; + } - return MutableMutabilityPlan.INSTANCE; - } ); + public JavaType resolveArrayDescriptor(Class elementJavaType) { + return resolveDescriptor( elementJavaType + "[]", + () -> createArrayTypeDescriptor( elementJavaType, JavaTypeRegistry::createMutabilityPlan) ); } public JavaType resolveDescriptor( Type javaType, BiFunction> mutabilityPlanCreator) { return resolveDescriptor( - javaType, + javaType.getTypeName(), () -> { if ( javaType instanceof ParameterizedType parameterizedType ) { final JavaType rawType = findDescriptor( parameterizedType.getRawType() ); @@ -134,33 +145,32 @@ public JavaType resolveDescriptor( return rawType.createJavaType( parameterizedType, typeConfiguration ); } } - final Type elementJavaType; - JavaType elementTypeDescriptor; - if ( javaType instanceof Class && ( (Class) javaType ).isArray() ) { - elementJavaType = ( (Class) javaType ).getComponentType(); - elementTypeDescriptor = findDescriptor( elementJavaType ); - } - else { - elementJavaType = javaType; - elementTypeDescriptor = null; - } - if ( elementTypeDescriptor == null ) { - //noinspection unchecked - elementTypeDescriptor = RegistryHelper.INSTANCE.createTypeDescriptor( - elementJavaType, - () -> (MutabilityPlan) mutabilityPlanCreator.apply( elementJavaType, typeConfiguration ), - typeConfiguration - ); - } - if ( javaType != elementJavaType ) { + else if ( javaType instanceof Class javaClass && javaClass.isArray() ) { //noinspection unchecked - return (JavaType) new ArrayJavaType<>( elementTypeDescriptor ); + return (JavaType) createArrayTypeDescriptor( javaClass.getComponentType(), mutabilityPlanCreator ); } - return elementTypeDescriptor; + return createTypeDescriptor( javaType, mutabilityPlanCreator ); } ); } + private JavaType createArrayTypeDescriptor(Class elementJavaType, BiFunction> mutabilityPlanCreator) { + JavaType elementTypeDescriptor = findDescriptor( elementJavaType ); + if ( elementTypeDescriptor == null ) { + elementTypeDescriptor = createTypeDescriptor( elementJavaType, mutabilityPlanCreator ); + } + return new ArrayJavaType<>( elementTypeDescriptor ); + } + + private JavaType createTypeDescriptor(Type javaType, BiFunction> mutabilityPlanCreator) { + //noinspection unchecked + return RegistryHelper.INSTANCE.createTypeDescriptor( + javaType, + () -> (MutabilityPlan) mutabilityPlanCreator.apply( javaType, typeConfiguration ), + typeConfiguration + ); + } + public JavaType resolveManagedTypeDescriptor(Type javaType) { return resolveManagedTypeDescriptor( javaType, false ); } From 8d9784f0bc867a5d851a47b1c14ed796f54bafbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Mon, 6 Jan 2025 15:10:04 +0100 Subject: [PATCH 06/11] HHH-18976 Consistently use Object[] instead of T[] in ArrayJdbcType The underlying JDBC driver only needs Object[], so there's no need to try hard to create a T[]. --- .../type/descriptor/jdbc/ArrayJdbcType.java | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java index 7581cf78625b..a5d5429a1040 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java @@ -147,28 +147,18 @@ protected Object[] getArray(BasicBinder binder, ValueBinder elementBin //noinspection unchecked final JavaType javaType = (JavaType) binder.getJavaType(); if ( elementJdbcType instanceof AggregateJdbcType ) { - final T[] domainObjects = (T[]) javaType.unwrap( value, Object[].class, options ); + final Object[] domainObjects = javaType.unwrap( value, Object[].class, options ); final Object[] objects = new Object[domainObjects.length]; for ( int i = 0; i < domainObjects.length; i++ ) { if ( domainObjects[i] != null ) { - objects[i] = elementBinder.getBindValue( domainObjects[i], options ); + //noinspection unchecked + objects[i] = elementBinder.getBindValue( (T) domainObjects[i], options ); } } return objects; } else { - final TypeConfiguration typeConfiguration = options.getTypeConfiguration(); - final JdbcType underlyingJdbcType = - typeConfiguration.getJdbcTypeRegistry().getDescriptor( elementJdbcType.getDefaultSqlTypeCode() ); - final Class preferredJavaTypeClass = elementJdbcType.getPreferredJavaTypeClass( options ); - final Class elementJdbcJavaTypeClass = - preferredJavaTypeClass == null - ? underlyingJdbcType.getJdbcRecommendedJavaTypeMapping(null, null, typeConfiguration ) - .getJavaTypeClass() - : preferredJavaTypeClass; - final Class arrayClass = (Class) - Array.newInstance( elementJdbcJavaTypeClass, 0 ).getClass(); - return javaType.unwrap( value, arrayClass, options ); + return javaType.unwrap( value, Object[].class, options ); } } From 3136e6adfe2d3127fcda9b764a6958c1822c74df Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Thu, 2 Jan 2025 15:50:08 +0100 Subject: [PATCH 07/11] HHH-16809 Add JavaType#createTypedArray / JavaType#getArrayType() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://hibernate.atlassian.net/browse/HHH-16809 Note these methods only handle arrays of objects (T[], Object[]) and not arrays of primitives (e.g. int[]), but that's fine as all the replaced calls were manipulating arrays of objects. In most cases they were manipulating an array of JavaType.getJavaTypeClass(), and that class represents the generic parameter T in JavaType, which can be many things but never a primitive type, since generics don't support primitive types. Co-Authored-By: Yoann Rodière --- .../internal/CollectionConverter.java | 6 +---- .../java/AbstractArrayJavaType.java | 7 +----- .../type/descriptor/java/JavaType.java | 23 +++++++++++++++++++ .../java/spi/BasicCollectionJavaType.java | 4 +--- .../type/descriptor/jdbc/ArrayJdbcType.java | 6 ++--- 5 files changed, 28 insertions(+), 18 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/CollectionConverter.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/CollectionConverter.java index c997d216b77a..82ae2de37a93 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/CollectionConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/CollectionConverter.java @@ -4,7 +4,6 @@ */ package org.hibernate.type.descriptor.converter.internal; -import java.lang.reflect.Array; import java.util.Collection; import org.hibernate.internal.build.AllowReflection; @@ -49,10 +48,7 @@ public Y toRelationalValue(X domainForm) { if ( domainForm == null ) { return null; } - final Object[] relationalArray = (Object[]) Array.newInstance( - elementConverter.getRelationalJavaType().getJavaTypeClass(), - domainForm.size() - ); + final Object[] relationalArray = elementConverter.getRelationalJavaType().createTypedArray( domainForm.size() ); int i = 0; for ( Object domainValue : domainForm ) { relationalArray[i++] = elementConverter.toRelationalValue( domainValue ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java index 333f2cce40a7..dc0fc4fbb3dd 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java @@ -4,11 +4,8 @@ */ package org.hibernate.type.descriptor.java; -import java.lang.reflect.Array; - import org.hibernate.MappingException; import org.hibernate.dialect.Dialect; -import org.hibernate.internal.build.AllowReflection; import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation; import org.hibernate.type.descriptor.converter.internal.ArrayConverter; import org.hibernate.type.BasicArrayType; @@ -21,7 +18,6 @@ import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; import org.hibernate.type.spi.TypeConfiguration; -@AllowReflection public abstract class AbstractArrayJavaType extends AbstractClassJavaType implements BasicPluralJavaType { @@ -86,8 +82,7 @@ BasicType createTypeUsingConverter( ColumnTypeInformation columnTypeInformation, JdbcTypeIndicators stdIndicators, BasicValueConverter valueConverter) { - final Class convertedElementClass = valueConverter.getRelationalJavaType().getJavaTypeClass(); - final Class convertedArrayClass = Array.newInstance( convertedElementClass, 0 ).getClass(); + final Class convertedArrayClass = valueConverter.getRelationalJavaType().getArrayType(); final JavaType relationalJavaType = typeConfiguration.getJavaTypeRegistry().getDescriptor( convertedArrayClass ); return new ConvertedBasicArrayType<>( elementType, diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java index 4e1095b65c02..144acff993b5 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java @@ -5,6 +5,7 @@ package org.hibernate.type.descriptor.java; import java.io.Serializable; +import java.lang.reflect.Array; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Comparator; @@ -328,6 +329,28 @@ default JavaType createJavaType(ParameterizedType parameterizedType, TypeConf return this; } + /** + * Creates a typed array, as opposed to a generic {@code Object[]} that holds the typed values. + *

+ * The array type necessarily extends {@code Object[]}: it will never be an array of primitives like {@code int[]}. + * + * @param numberOfElements The size of the array to create + */ + @SuppressWarnings("unchecked") + default T[] createTypedArray(int numberOfElements) { + return (T[]) Array.newInstance( getJavaTypeClass(), numberOfElements ); + } + + /** + * Get the Java type (the {@link Class} object) representing an array with elements of this {@code JavaType}. + *

+ * The array type necessarily extends {@code Object[]}: it will never be an array of primitives like {@code int[]}. + */ + @SuppressWarnings("unchecked") + default Class getArrayType() { + return (Class) createTypedArray( 0 ).getClass(); + } + /** * Return true if the implementation is an instance of {@link TemporalJavaType} * diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java index cbdef1177c54..6e12e0b92b66 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java @@ -133,9 +133,7 @@ public BasicType resolveType( ); } else { - final Class arrayClass = - Array.newInstance( valueConverter.getRelationalJavaType().getJavaTypeClass(), 0 ) - .getClass(); + final Class arrayClass = valueConverter.getRelationalJavaType().getArrayType(); final JavaType relationalJavaType = typeConfiguration.getJavaTypeRegistry().resolveDescriptor( arrayClass ); //noinspection unchecked,rawtypes diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java index a5d5429a1040..064ea73ac6c2 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java @@ -41,7 +41,6 @@ * @author Christian Beikov * @author Jordan Gigov */ -@AllowReflection // See https://hibernate.atlassian.net/browse/HHH-16809 public class ArrayJdbcType implements JdbcType { private final JdbcType elementJdbcType; @@ -69,9 +68,8 @@ public JavaType getJdbcRecommendedJavaTypeMapping( scale, typeConfiguration ); - final JavaType javaType = typeConfiguration.getJavaTypeRegistry().resolveDescriptor( - Array.newInstance( elementJavaType.getJavaTypeClass(), 0 ).getClass() - ); + final JavaType javaType = typeConfiguration.getJavaTypeRegistry() + .resolveDescriptor( elementJavaType.getArrayType() ); if ( javaType instanceof BasicPluralType ) { //noinspection unchecked return (JavaType) javaType; From 174f593e5e26e0df621bcf1e5ab492ef19c0ad67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Fri, 3 Jan 2025 12:05:49 +0100 Subject: [PATCH 08/11] HHH-16809 Rename JavaType#createTypedArray to newArray and getArrayType to getArrayClass For consistency with: 1. PrimitiveJavaType#getArrayClass 2. Array#newInstance --- .../converter/internal/CollectionConverter.java | 2 +- .../type/descriptor/java/AbstractArrayJavaType.java | 2 +- .../java/org/hibernate/type/descriptor/java/JavaType.java | 8 ++++---- .../type/descriptor/java/spi/BasicCollectionJavaType.java | 2 +- .../org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java | 3 +-- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/CollectionConverter.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/CollectionConverter.java index 82ae2de37a93..690a050fa57d 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/CollectionConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/CollectionConverter.java @@ -48,7 +48,7 @@ public Y toRelationalValue(X domainForm) { if ( domainForm == null ) { return null; } - final Object[] relationalArray = elementConverter.getRelationalJavaType().createTypedArray( domainForm.size() ); + final Object[] relationalArray = elementConverter.getRelationalJavaType().newArray( domainForm.size() ); int i = 0; for ( Object domainValue : domainForm ) { relationalArray[i++] = elementConverter.toRelationalValue( domainValue ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java index dc0fc4fbb3dd..7e61a30ba781 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractArrayJavaType.java @@ -82,7 +82,7 @@ BasicType createTypeUsingConverter( ColumnTypeInformation columnTypeInformation, JdbcTypeIndicators stdIndicators, BasicValueConverter valueConverter) { - final Class convertedArrayClass = valueConverter.getRelationalJavaType().getArrayType(); + final Class convertedArrayClass = valueConverter.getRelationalJavaType().getArrayClass(); final JavaType relationalJavaType = typeConfiguration.getJavaTypeRegistry().getDescriptor( convertedArrayClass ); return new ConvertedBasicArrayType<>( elementType, diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java index 144acff993b5..a312ac8c3a60 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java @@ -330,14 +330,14 @@ default JavaType createJavaType(ParameterizedType parameterizedType, TypeConf } /** - * Creates a typed array, as opposed to a generic {@code Object[]} that holds the typed values. + * Creates a typed object array, as opposed to a generic {@code Object[]} that holds the typed values. *

* The array type necessarily extends {@code Object[]}: it will never be an array of primitives like {@code int[]}. * * @param numberOfElements The size of the array to create */ @SuppressWarnings("unchecked") - default T[] createTypedArray(int numberOfElements) { + default T[] newArray(int numberOfElements) { return (T[]) Array.newInstance( getJavaTypeClass(), numberOfElements ); } @@ -347,8 +347,8 @@ default T[] createTypedArray(int numberOfElements) { * The array type necessarily extends {@code Object[]}: it will never be an array of primitives like {@code int[]}. */ @SuppressWarnings("unchecked") - default Class getArrayType() { - return (Class) createTypedArray( 0 ).getClass(); + default Class getArrayClass() { + return (Class) newArray( 0 ).getClass(); } /** diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java index 6e12e0b92b66..524a80344f7c 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java @@ -133,7 +133,7 @@ public BasicType resolveType( ); } else { - final Class arrayClass = valueConverter.getRelationalJavaType().getArrayType(); + final Class arrayClass = valueConverter.getRelationalJavaType().getArrayClass(); final JavaType relationalJavaType = typeConfiguration.getJavaTypeRegistry().resolveDescriptor( arrayClass ); //noinspection unchecked,rawtypes diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java index 064ea73ac6c2..6b65da256323 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java @@ -17,7 +17,6 @@ import org.hibernate.dialect.StructHelper; import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.internal.build.AllowReflection; import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.type.BasicPluralType; import org.hibernate.type.descriptor.ValueBinder; @@ -69,7 +68,7 @@ public JavaType getJdbcRecommendedJavaTypeMapping( typeConfiguration ); final JavaType javaType = typeConfiguration.getJavaTypeRegistry() - .resolveDescriptor( elementJavaType.getArrayType() ); + .resolveDescriptor( elementJavaType.getArrayClass() ); if ( javaType instanceof BasicPluralType ) { //noinspection unchecked return (JavaType) javaType; From 689e7490376d50446c85ef32329755755b3bbd06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Fri, 3 Jan 2025 12:53:35 +0100 Subject: [PATCH 09/11] WIP implement newArray/getArrayClass --- .../type/descriptor/java/BooleanJavaType.java | 5 +++++ .../hibernate/type/descriptor/java/ByteJavaType.java | 5 +++++ .../type/descriptor/java/CalendarDateJavaType.java | 10 ++++++++++ .../type/descriptor/java/CalendarJavaType.java | 10 ++++++++++ .../type/descriptor/java/CalendarTimeJavaType.java | 10 ++++++++++ .../type/descriptor/java/CharacterJavaType.java | 5 +++++ .../hibernate/type/descriptor/java/DateJavaType.java | 10 ++++++++++ .../type/descriptor/java/DoubleJavaType.java | 5 +++++ .../hibernate/type/descriptor/java/FloatJavaType.java | 5 +++++ .../type/descriptor/java/InstantJavaType.java | 10 ++++++++++ .../type/descriptor/java/IntegerJavaType.java | 5 +++++ .../type/descriptor/java/JdbcDateJavaType.java | 10 ++++++++++ .../type/descriptor/java/JdbcTimeJavaType.java | 10 ++++++++++ .../type/descriptor/java/JdbcTimestampJavaType.java | 10 ++++++++++ .../type/descriptor/java/LocalDateJavaType.java | 10 ++++++++++ .../type/descriptor/java/LocalDateTimeJavaType.java | 10 ++++++++++ .../type/descriptor/java/LocalTimeJavaType.java | 10 ++++++++++ .../hibernate/type/descriptor/java/LongJavaType.java | 5 +++++ .../type/descriptor/java/OffsetDateTimeJavaType.java | 10 ++++++++++ .../type/descriptor/java/OffsetTimeJavaType.java | 10 ++++++++++ .../hibernate/type/descriptor/java/ShortJavaType.java | 5 +++++ .../type/descriptor/java/ZonedDateTimeJavaType.java | 10 ++++++++++ .../descriptor/java/spi/DynamicModelJavaType.java | 11 +++++++++++ 23 files changed, 191 insertions(+) diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanJavaType.java index 03fae3c28c93..865d407978b4 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BooleanJavaType.java @@ -156,6 +156,11 @@ public Class getPrimitiveClass() { return boolean.class; } + @Override + public Boolean[] newArray(int numberOfElements) { + return new Boolean[numberOfElements]; + } + @Override public Class getArrayClass() { return Boolean[].class; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ByteJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ByteJavaType.java index 87e4f609e17e..f1ed57cd71c9 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ByteJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ByteJavaType.java @@ -96,6 +96,11 @@ public Class getPrimitiveClass() { return byte.class; } + @Override + public Byte[] newArray(int numberOfElements) { + return new Byte[numberOfElements]; + } + @Override public Class getArrayClass() { return Byte[].class; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarDateJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarDateJavaType.java index 940c5201a589..694fb63fa715 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarDateJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarDateJavaType.java @@ -136,6 +136,16 @@ public boolean isWider(JavaType javaType) { }; } + @Override + public Calendar[] newArray(int numberOfElements) { + return new Calendar[numberOfElements]; + } + + @Override + public Class getArrayClass() { + return Calendar[].class; + } + @Override public int getDefaultSqlPrecision(Dialect dialect, JdbcType jdbcType) { return 0; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarJavaType.java index e4d49d274fe4..6b9b5de445f6 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarJavaType.java @@ -154,6 +154,16 @@ public boolean isWider(JavaType javaType) { }; } + @Override + public Calendar[] newArray(int numberOfElements) { + return new Calendar[numberOfElements]; + } + + @Override + public Class getArrayClass() { + return Calendar[].class; + } + @Override public int getDefaultSqlPrecision(Dialect dialect, JdbcType jdbcType) { return dialect.getDefaultTimestampPrecision(); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarTimeJavaType.java index d480795b7f68..4e671e597748 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarTimeJavaType.java @@ -138,6 +138,16 @@ public boolean isWider(JavaType javaType) { }; } + @Override + public Calendar[] newArray(int numberOfElements) { + return new Calendar[numberOfElements]; + } + + @Override + public Class getArrayClass() { + return Calendar[].class; + } + @Override public int getDefaultSqlPrecision(Dialect dialect, JdbcType jdbcType) { // times represent repeating events - they diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CharacterJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CharacterJavaType.java index f240db0f10b3..5d214c385f8b 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CharacterJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CharacterJavaType.java @@ -96,6 +96,11 @@ public Class getPrimitiveClass() { return char.class; } + @Override + public Character[] newArray(int numberOfElements) { + return new Character[numberOfElements]; + } + @Override public Class getArrayClass() { return Character[].class; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DateJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DateJavaType.java index e9e005a724b6..a7a4638770a5 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DateJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DateJavaType.java @@ -174,6 +174,16 @@ public boolean isWider(JavaType javaType) { }; } + @Override + public Date[] newArray(int numberOfElements) { + return new Date[numberOfElements]; + } + + @Override + public Class getArrayClass() { + return Date[].class; + } + @Override public Date next( Date current, diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoubleJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoubleJavaType.java index 191ec6462a55..c4bf9c201c4c 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoubleJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DoubleJavaType.java @@ -121,6 +121,11 @@ public Class getPrimitiveClass() { return double.class; } + @Override + public Double[] newArray(int numberOfElements) { + return new Double[numberOfElements]; + } + @Override public Class getArrayClass() { return Double[].class; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatJavaType.java index cb200bed4d24..ab8b5161c876 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/FloatJavaType.java @@ -119,6 +119,11 @@ public Class getPrimitiveClass() { return float.class; } + @Override + public Float[] newArray(int numberOfElements) { + return new Float[numberOfElements]; + } + @Override public Class getArrayClass() { return Float[].class; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/InstantJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/InstantJavaType.java index 4d5e80b0bb7f..c9172ac5b30e 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/InstantJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/InstantJavaType.java @@ -188,6 +188,16 @@ public Instant wrap(X value, WrapperOptions options) { throw unknownWrap( value.getClass() ); } + @Override + public Instant[] newArray(int numberOfElements) { + return new Instant[numberOfElements]; + } + + @Override + public Class getArrayClass() { + return Instant[].class; + } + @Override public int getDefaultSqlPrecision(Dialect dialect, JdbcType jdbcType) { return dialect.getDefaultTimestampPrecision(); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerJavaType.java index c28bc26b7a66..32c36ac4f07c 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/IntegerJavaType.java @@ -112,6 +112,11 @@ public Class getPrimitiveClass() { return int.class; } + @Override + public Integer[] newArray(int numberOfElements) { + return new Integer[numberOfElements]; + } + @Override public Class getArrayClass() { return Integer[].class; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcDateJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcDateJavaType.java index 4859d2c16b26..1cf4641d9945 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcDateJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcDateJavaType.java @@ -210,6 +210,16 @@ public Date wrap(Object value, WrapperOptions options) { throw unknownWrap( value.getClass() ); } + @Override + public Date[] newArray(int numberOfElements) { + return new Date[numberOfElements]; + } + + @Override + public Class getArrayClass() { + return Date[].class; + } + @Override public String toString(Date value) { if ( value instanceof java.sql.Date ) { diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimeJavaType.java index 279c39c9af02..0c8b08408e56 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimeJavaType.java @@ -203,6 +203,16 @@ public Date wrap(Object value, WrapperOptions options) { throw unknownWrap( value.getClass() ); } + @Override + public Date[] newArray(int numberOfElements) { + return new Date[numberOfElements]; + } + + @Override + public Class getArrayClass() { + return Date[].class; + } + @Override public String toString(Date value) { if ( value instanceof java.sql.Time time ) { diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java index 0a309d920187..0bb50a98cb2e 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java @@ -197,6 +197,16 @@ public boolean isWider(JavaType javaType) { }; } + @Override + public Date[] newArray(int numberOfElements) { + return new Date[numberOfElements]; + } + + @Override + public Class getArrayClass() { + return Date[].class; + } + @Override public String toString(Date value) { return LITERAL_FORMATTER.format( value.toInstant() ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateJavaType.java index 34765bfdc209..204e3ae67f7e 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateJavaType.java @@ -170,4 +170,14 @@ public boolean isWider(JavaType javaType) { }; } + @Override + public LocalDate[] newArray(int numberOfElements) { + return new LocalDate[numberOfElements]; + } + + @Override + public Class getArrayClass() { + return LocalDate[].class; + } + } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateTimeJavaType.java index a1e2bb1a3f32..05999edbd5d7 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateTimeJavaType.java @@ -168,6 +168,16 @@ public boolean isWider(JavaType javaType) { }; } + @Override + public LocalDateTime[] newArray(int numberOfElements) { + return new LocalDateTime[numberOfElements]; + } + + @Override + public Class getArrayClass() { + return LocalDateTime[].class; + } + @Override public int getDefaultSqlPrecision(Dialect dialect, JdbcType jdbcType) { return dialect.getDefaultTimestampPrecision(); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalTimeJavaType.java index 58654f51b5ca..bf0c57ef4d97 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalTimeJavaType.java @@ -179,6 +179,16 @@ public boolean isWider(JavaType javaType) { }; } + @Override + public LocalTime[] newArray(int numberOfElements) { + return new LocalTime[numberOfElements]; + } + + @Override + public Class getArrayClass() { + return LocalTime[].class; + } + @Override public int getDefaultSqlPrecision(Dialect dialect, JdbcType jdbcType) { // times represent repeating events - they diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongJavaType.java index b2762632cfb7..77d74a678945 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LongJavaType.java @@ -167,6 +167,11 @@ public Class getPrimitiveClass() { return long.class; } + @Override + public Long[] newArray(int numberOfElements) { + return new Long[numberOfElements]; + } + @Override public Class getArrayClass() { return Long[].class; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java index bccfd17dea9e..85e3aa7b0de4 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java @@ -228,6 +228,16 @@ public OffsetDateTime wrap(X value, WrapperOptions options) { throw unknownWrap( value.getClass() ); } + @Override + public OffsetDateTime[] newArray(int numberOfElements) { + return new OffsetDateTime[numberOfElements]; + } + + @Override + public Class getArrayClass() { + return OffsetDateTime[].class; + } + @Override public int getDefaultSqlPrecision(Dialect dialect, JdbcType jdbcType) { return dialect.getDefaultTimestampPrecision(); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetTimeJavaType.java index ec55e2d78104..e81baca732f1 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetTimeJavaType.java @@ -242,6 +242,16 @@ private static ZoneOffset getCurrentSystemOffset() { return OffsetDateTime.now().getOffset(); } + @Override + public OffsetTime[] newArray(int numberOfElements) { + return new OffsetTime[numberOfElements]; + } + + @Override + public Class getArrayClass() { + return OffsetTime[].class; + } + @Override public int getDefaultSqlPrecision(Dialect dialect, JdbcType jdbcType) { // times represent repeating events - they diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortJavaType.java index 60f9278a0206..953ab1747192 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ShortJavaType.java @@ -103,6 +103,11 @@ public Class getPrimitiveClass() { return short.class; } + @Override + public Short[] newArray(int numberOfElements) { + return new Short[numberOfElements]; + } + @Override public Class getArrayClass() { return Short[].class; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZonedDateTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZonedDateTimeJavaType.java index 35bae1aeffc9..d412d92ed98c 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZonedDateTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZonedDateTimeJavaType.java @@ -190,6 +190,16 @@ public ZonedDateTime wrap(X value, WrapperOptions options) { throw unknownWrap( value.getClass() ); } + @Override + public ZonedDateTime[] newArray(int numberOfElements) { + return new ZonedDateTime[numberOfElements]; + } + + @Override + public Class getArrayClass() { + return ZonedDateTime[].class; + } + @Override public int getDefaultSqlPrecision(Dialect dialect, JdbcType jdbcType) { return dialect.getDefaultTimestampPrecision(); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/DynamicModelJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/DynamicModelJavaType.java index c6c087da71a9..35d867cc7eca 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/DynamicModelJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/DynamicModelJavaType.java @@ -43,4 +43,15 @@ public Class> getJavaTypeClass() { //noinspection unchecked,rawtypes return (Class) Map.class; } + + @Override + public Map[] newArray(int numberOfElements) { + return new Map[numberOfElements]; + } + + @Override + @SuppressWarnings({"unchecked", "rawtypes", "RedundantCast"}) + public Class[]> getArrayClass() { + return (Class[]>) (Class) Map[].class; + } } From 3f054645bc6f626d76ddc9de48ea2b46cf77479f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Mon, 6 Jan 2025 16:49:56 +0100 Subject: [PATCH 10/11] HHH-18976 Replace unnecessary dynamic array instantiations with calls to new Object[] The dynamic instantiations were originally introduced to fix the following issues: * HHH-17201 -- tested in MultiIdEntityLoadTests The corresponding tests still pass after removing these dynamic array instantiations. --- .../org/hibernate/internal/MultiIdentifierLoadAccessImpl.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/internal/MultiIdentifierLoadAccessImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/MultiIdentifierLoadAccessImpl.java index 35ac407f81fc..66736d014bea 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/MultiIdentifierLoadAccessImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/MultiIdentifierLoadAccessImpl.java @@ -19,7 +19,6 @@ import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.RootGraph; import org.hibernate.graph.spi.RootGraphImplementor; -import org.hibernate.loader.ast.internal.LoaderHelper; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.loader.ast.spi.MultiIdLoadOptions; @@ -191,7 +190,7 @@ public List multiLoad(List ids) { } else { return perform( () -> (List) entityPersister.multiLoad( - ids.toArray( LoaderHelper.createTypedArray( ids.get( 0 ).getClass(), ids.size() ) ), + ids.toArray( new Object[0] ), session, this ) ); From 83735663dc7394410bf1c4687db4f2221c0d3c48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Fri, 3 Jan 2025 15:25:31 +0100 Subject: [PATCH 11/11] HHH-18976 Remove now-unused helper methods that perform dynamic array instantiation --- .../util/collections/ArrayHelper.java | 19 ------------------- .../loader/ast/internal/LoaderHelper.java | 16 +++------------- rules/forbidden-apis.txt | 2 -- 3 files changed, 3 insertions(+), 34 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java index 7b7e5a940441..778718cd0db3 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/ArrayHelper.java @@ -59,14 +59,6 @@ public static int indexOf(Object[] array, int end, Object object) { return -1; } - @SuppressWarnings("unchecked") - @AllowReflection - public static T[] filledArray(T value, Class valueJavaType, int size) { - final T[] array = (T[]) Array.newInstance( valueJavaType, size ); - Arrays.fill( array, value ); - return array; - } - public static String[] toStringArray(Object[] objects) { int length = objects.length; String[] result = new String[length]; @@ -521,15 +513,4 @@ public static void forEach(T[] array, Consumer consumer) { consumer.accept( array[ i ] ); } } - - /** - * @deprecated Use {@link Array#newInstance(Class, int)} instead. - */ - @Deprecated - @SuppressWarnings("unchecked") - @AllowReflection - public static T[] newInstance(Class elementType, int length) { - return (T[]) Array.newInstance( elementType, length ); - } - } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderHelper.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderHelper.java index 3ad14036c4e3..e88fa6aec2f8 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderHelper.java @@ -169,6 +169,7 @@ public static Boolean getReadOnlyFromLoadQueryInfluencers(LoadQueryInfluencers l * * @param The key type */ + @AllowReflection public static K[] normalizeKeys( K[] keys, BasicValuedModelPart keyPart, @@ -184,7 +185,8 @@ public static K[] normalizeKeys( return keys; } - final K[] typedArray = createTypedArray( keyClass, keys.length ); + //noinspection unchecked + final K[] typedArray = (K[]) Array.newInstance( keyClass, keys.length ); final boolean coerce = !sessionFactory.getJpaMetamodel().getJpaCompliance().isLoadByIdComplianceEnabled(); if ( !coerce ) { System.arraycopy( keys, 0, typedArray, 0, keys.length ); @@ -197,18 +199,6 @@ public static K[] normalizeKeys( return typedArray; } - /** - * Creates a typed array, as opposed to a generic {@code Object[]} that holds the typed values - * - * @param elementClass The type of the array elements. See {@link Class#getComponentType()} - * @param length The length to which the array should be created. This is usually zero for Hibernate uses - */ - @AllowReflection - public static X[] createTypedArray(Class elementClass, @SuppressWarnings("SameParameterValue") int length) { - //noinspection unchecked - return (X[]) Array.newInstance( elementClass, length ); - } - /** * Load one or more instances of a model part (an entity or collection) * based on a SQL ARRAY parameter to specify the keys (as opposed to the diff --git a/rules/forbidden-apis.txt b/rules/forbidden-apis.txt index 01007e7b26c1..99b433204d28 100644 --- a/rules/forbidden-apis.txt +++ b/rules/forbidden-apis.txt @@ -11,8 +11,6 @@ java.lang.reflect.Array#newInstance(java.lang.Class, int) java.lang.reflect.Array#newInstance(java.lang.Class, int[]) -org.hibernate.internal.util.collections.ArrayHelper#newInstance(java.lang.Class, int) -org.hibernate.internal.util.collections.ArrayHelper#filledArray(java.lang.Object, java.lang.Class, int) org.hibernate.internal.util.collections.ArrayHelper#join(java.lang.Object[], java.lang.Object[]) ################################################################################################################