From 079c59540572a5aa9549cf7effb7c2f2ec69f58e Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 5 Sep 2025 22:45:06 +0200 Subject: [PATCH 1/2] HHH-19276 - Avoid use of == in ArrayAndElementArgumentValidator --- .../function/array/ArrayAndElementArgumentValidator.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayAndElementArgumentValidator.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayAndElementArgumentValidator.java index 4c87172ac87c..c040c28e6f01 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayAndElementArgumentValidator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/array/ArrayAndElementArgumentValidator.java @@ -39,7 +39,9 @@ public void validate( final SqmTypedNode elementArgument = arguments.get( elementIndex ); final SqmBindableType expressible = elementArgument.getExpressible(); final SqmExpressible elementType = expressible != null ? expressible.getSqmType() : null; - if ( expectedElementType != null && elementType != null && expectedElementType != elementType ) { + if ( expectedElementType != null && elementType != null + && !expectedElementType.getJavaType() + .isAssignableFrom( elementType.getExpressibleJavaType().getJavaTypeClass() ) ) { throw new FunctionArgumentException( String.format( "Parameter %d of function '%s()' has type %s, but argument is of type '%s'", From 0a5ab82deccc6789cb18d9651137168d833c9951 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 5 Sep 2025 22:31:17 +0200 Subject: [PATCH 2/2] HHH-19276 - Native query with enum list param leads to OutOfMemory The registryValues Map was dropped from BasicTypeRegistry since it's no longer needed, and it could lead to an OutOfMemoryError (accumulation of EnumJavaType instances as keys in the Map). --- .../org/hibernate/type/BasicTypeRegistry.java | 46 +------------------ 1 file changed, 1 insertion(+), 45 deletions(-) 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 dbfa354a69ff..92e0a6e13423 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/BasicTypeRegistry.java +++ b/hibernate-core/src/main/java/org/hibernate/type/BasicTypeRegistry.java @@ -46,7 +46,6 @@ public class BasicTypeRegistry implements Serializable { private final TypeConfiguration typeConfiguration; - private final Map, BasicType>> registryValues = new ConcurrentHashMap<>(); private boolean primed; private final Map> typesByName = new ConcurrentHashMap<>(); @@ -94,7 +93,6 @@ private BasicType createBasicType(String name, BasicTypeReference type final var javaType = getJavaTypeRegistry().resolveDescriptor( typeReference.getJavaType() ); final var jdbcType = getJdbcTypeRegistry().getDescriptor( typeReference.getSqlTypeCode() ); final var createdType = createBasicType( typeReference, javaType, jdbcType ); - primeRegistryEntry( createdType ); typesByName.put( typeReference.getName(), createdType ); typesByName.put( name, createdType ); return createdType; @@ -245,11 +243,7 @@ public BasicType resolve(JavaType javaType, JdbcType jdbcType, String * JdbcType combo or create (and register) one. */ public BasicType resolve(JavaType javaType, JdbcType jdbcType, Supplier> creator) { - final var registeredBasicType = registryForJdbcType( jdbcType ).get( javaType ); - //noinspection unchecked - return registeredBasicType != null - ? (BasicType) registeredBasicType - : createIfUnregistered( javaType, jdbcType, creator ); + return createIfUnregistered( javaType, jdbcType, creator ); } private BasicType createIfUnregistered( @@ -277,7 +271,6 @@ private static boolean registeredTypeMatches(JavaType javaType, JdbcType private void register(JavaType javaType, JdbcType jdbcType, BasicType createdType) { if ( createdType != null ) { - registryForJdbcType( jdbcType ).put( javaType, createdType ); // if we are still building mappings, register this adhoc // type via a unique code. (This is to support Envers.) try { @@ -313,8 +306,6 @@ public void register(BasicType type, String... keys) { throw new HibernateException( "Type to register cannot be null" ); } - applyOrOverwriteEntry( type ); - // explicit registration keys if ( isEmpty( keys ) ) { LOG.typeDefinedNoRegistrationKeys( type ); @@ -324,19 +315,6 @@ public void register(BasicType type, String... keys) { } } - private void applyOrOverwriteEntry(BasicType type) { - final var jdbcType = type.getJdbcType(); - final var existing = registryForJdbcType( jdbcType ).put( type.getMappedJavaType(), type ); - if ( existing != null ) { - LOG.tracef( - "BasicTypeRegistry registration overwritten (%s + %s); previous =`%s`", - jdbcType.getFriendlyName(), - type.getJavaTypeDescriptor(), - existing - ); - } - } - public CustomType register(UserType type, String... keys) { final var customType = new CustomType<>( type, keys, typeConfiguration ); register( customType ); @@ -381,8 +359,6 @@ public void addPrimeEntry(BasicType type, String legacyTypeClassName, String[ throw new HibernateException( "Type to register cannot be null" ); } - primeRegistryEntry( type ); - // Legacy name registration if ( isNotEmpty( legacyTypeClassName ) ) { typesByName.put( legacyTypeClassName, type ); @@ -420,26 +396,6 @@ public void addPrimeEntry(BasicTypeReference type, String legacyTypeClassName } } - private void primeRegistryEntry(BasicType type) { - final var jdbcType = type.getJdbcType(); - final var existing = registryForJdbcType( jdbcType ).get( type.getMappedJavaType() ); - if ( existing != null ) { - LOG.tracef( - "Skipping registration of BasicType (%s + %s); still priming. existing = %s", - jdbcType.getFriendlyName(), - type.getJavaTypeDescriptor(), - existing - ); - } - else { - registryForJdbcType( jdbcType ).put( type.getMappedJavaType(), type ); - } - } - - private Map, BasicType> registryForJdbcType(JdbcType jdbcType) { - return registryValues.computeIfAbsent( jdbcType, key -> new ConcurrentHashMap<>() ); - } - private void applyRegistrationKeys(BasicType type, String[] keys) { for ( String key : keys ) { if ( key != null ) {