HHH-17662 Replace JdbcTypeConstructor uses for arrays with uniform resolve method

This commit is contained in:
Christian Beikov 2024-01-24 11:38:08 +01:00
parent 43341da00f
commit 5bd7e86e92
13 changed files with 228 additions and 172 deletions

View File

@ -300,15 +300,13 @@ public JdbcType resolveSqlTypeDescriptor(
} }
break; break;
case ARRAY: case ARRAY:
final JdbcTypeConstructor jdbcTypeConstructor = jdbcTypeRegistry.getConstructor( jdbcTypeCode );
// PostgreSQL names array types by prepending an underscore to the base name // PostgreSQL names array types by prepending an underscore to the base name
if ( jdbcTypeConstructor != null && columnTypeName.charAt( 0 ) == '_' ) { if ( columnTypeName.charAt( 0 ) == '_' ) {
final String componentTypeName = columnTypeName.substring( 1 ); final String componentTypeName = columnTypeName.substring( 1 );
final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() ); final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() );
if ( sqlTypeCode != null ) { if ( sqlTypeCode != null ) {
return jdbcTypeConstructor.resolveType( return jdbcTypeRegistry.resolveTypeConstructorDescriptor(
jdbcTypeRegistry.getTypeConfiguration(), jdbcTypeCode,
this,
jdbcTypeRegistry.getDescriptor( sqlTypeCode ), jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
ColumnTypeInformation.EMPTY ColumnTypeInformation.EMPTY
); );

View File

@ -100,7 +100,6 @@
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType; import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
import org.hibernate.type.descriptor.jdbc.BlobJdbcType; import org.hibernate.type.descriptor.jdbc.BlobJdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor;
import org.hibernate.type.descriptor.jdbc.OracleJsonBlobJdbcType; import org.hibernate.type.descriptor.jdbc.OracleJsonBlobJdbcType;
import org.hibernate.type.descriptor.jdbc.NullJdbcType; import org.hibernate.type.descriptor.jdbc.NullJdbcType;
import org.hibernate.type.descriptor.jdbc.ObjectNullAsNullTypeJdbcType; import org.hibernate.type.descriptor.jdbc.ObjectNullAsNullTypeJdbcType;
@ -760,15 +759,11 @@ public JdbcType resolveSqlTypeDescriptor(
break; break;
case ARRAY: case ARRAY:
if ( "MDSYS.SDO_ORDINATE_ARRAY".equals( columnTypeName ) ) { if ( "MDSYS.SDO_ORDINATE_ARRAY".equals( columnTypeName ) ) {
final JdbcTypeConstructor jdbcTypeConstructor = jdbcTypeRegistry.getConstructor( jdbcTypeCode ); return jdbcTypeRegistry.resolveTypeConstructorDescriptor(
if ( jdbcTypeConstructor != null ) { jdbcTypeCode,
return jdbcTypeConstructor.resolveType( jdbcTypeRegistry.getDescriptor( NUMERIC ),
jdbcTypeRegistry.getTypeConfiguration(), ColumnTypeInformation.EMPTY
this, );
jdbcTypeRegistry.getDescriptor( NUMERIC ),
ColumnTypeInformation.EMPTY
);
}
} }
break; break;
case Types.NUMERIC: case Types.NUMERIC:

View File

@ -328,15 +328,13 @@ public JdbcType resolveSqlTypeDescriptor(
} }
break; break;
case ARRAY: case ARRAY:
final JdbcTypeConstructor jdbcTypeConstructor = jdbcTypeRegistry.getConstructor( jdbcTypeCode );
// PostgreSQL names array types by prepending an underscore to the base name // PostgreSQL names array types by prepending an underscore to the base name
if ( jdbcTypeConstructor != null && columnTypeName.charAt( 0 ) == '_' ) { if ( columnTypeName.charAt( 0 ) == '_' ) {
final String componentTypeName = columnTypeName.substring( 1 ); final String componentTypeName = columnTypeName.substring( 1 );
final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() ); final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() );
if ( sqlTypeCode != null ) { if ( sqlTypeCode != null ) {
return jdbcTypeConstructor.resolveType( return jdbcTypeRegistry.resolveTypeConstructorDescriptor(
jdbcTypeRegistry.getTypeConfiguration(), jdbcTypeCode,
this,
jdbcTypeRegistry.getDescriptor( sqlTypeCode ), jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
ColumnTypeInformation.EMPTY ColumnTypeInformation.EMPTY
); );

View File

@ -318,15 +318,13 @@ public JdbcType resolveSqlTypeDescriptor(
} }
break; break;
case ARRAY: case ARRAY:
final JdbcTypeConstructor jdbcTypeConstructor = jdbcTypeRegistry.getConstructor( jdbcTypeCode );
// PostgreSQL names array types by prepending an underscore to the base name // PostgreSQL names array types by prepending an underscore to the base name
if ( jdbcTypeConstructor != null && columnTypeName.charAt( 0 ) == '_' ) { if ( columnTypeName.charAt( 0 ) == '_' ) {
final String componentTypeName = columnTypeName.substring( 1 ); final String componentTypeName = columnTypeName.substring( 1 );
final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() ); final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() );
if ( sqlTypeCode != null ) { if ( sqlTypeCode != null ) {
return jdbcTypeConstructor.resolveType( return jdbcTypeRegistry.resolveTypeConstructorDescriptor(
jdbcTypeRegistry.getTypeConfiguration(), jdbcTypeCode,
this,
jdbcTypeRegistry.getDescriptor( sqlTypeCode ), jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
ColumnTypeInformation.EMPTY ColumnTypeInformation.EMPTY
); );

View File

@ -725,22 +725,18 @@ public JdbcType resolveSqlTypeDescriptor(
int scale, int scale,
JdbcTypeRegistry jdbcTypeRegistry) { JdbcTypeRegistry jdbcTypeRegistry) {
if ( jdbcTypeCode == ARRAY ) { if ( jdbcTypeCode == ARRAY ) {
final JdbcTypeConstructor jdbcTypeConstructor = jdbcTypeRegistry.getConstructor( jdbcTypeCode ); // Special handling for array types, because we need the proper element/component type
if ( jdbcTypeConstructor != null ) { // To determine the element JdbcType, we pass the database reported type to #resolveSqlTypeCode
// Special handling for array types, because we need the proper element/component type final int arraySuffixIndex = columnTypeName.toLowerCase( Locale.ROOT ).indexOf( " array" );
// To determine the element JdbcType, we pass the database reported type to #resolveSqlTypeCode if ( arraySuffixIndex != -1 ) {
final int arraySuffixIndex = columnTypeName.toLowerCase( Locale.ROOT ).indexOf( " array" ); final String componentTypeName = columnTypeName.substring( 0, arraySuffixIndex );
if ( arraySuffixIndex != -1 ) { final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() );
final String componentTypeName = columnTypeName.substring( 0, arraySuffixIndex ); if ( sqlTypeCode != null ) {
final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() ); return jdbcTypeRegistry.resolveTypeConstructorDescriptor(
if ( sqlTypeCode != null ) { jdbcTypeCode,
return jdbcTypeConstructor.resolveType( jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
jdbcTypeRegistry.getTypeConfiguration(), ColumnTypeInformation.EMPTY
this, );
jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
ColumnTypeInformation.EMPTY
);
}
} }
} }
} }

View File

@ -46,10 +46,21 @@ public JdbcType resolveType(
JdbcType elementType, JdbcType elementType,
ColumnTypeInformation columnTypeInformation) { ColumnTypeInformation columnTypeInformation) {
// a bit wrong, since columnTypeInformation.getTypeName() is typically null! // a bit wrong, since columnTypeInformation.getTypeName() is typically null!
return new OracleArrayJdbcType( String typeName = columnTypeInformation == null ? null : columnTypeInformation.getTypeName();
elementType, if ( typeName == null || typeName.isBlank() ) {
columnTypeInformation == null ? null : columnTypeInformation.getTypeName() Integer precision = null;
); Integer scale = null;
if ( columnTypeInformation != null ) {
precision = columnTypeInformation.getColumnSize();
scale = columnTypeInformation.getDecimalDigits();
}
typeName = OracleArrayJdbcType.getTypeName( elementType.getJdbcRecommendedJavaTypeMapping(
precision,
scale,
typeConfiguration
), dialect );
}
return new OracleArrayJdbcType( elementType, typeName );
} }
@Override @Override

View File

@ -799,15 +799,11 @@ public JdbcType resolveSqlTypeDescriptor(
break; break;
case ARRAY: case ARRAY:
if ( "MDSYS.SDO_ORDINATE_ARRAY".equals( columnTypeName ) ) { if ( "MDSYS.SDO_ORDINATE_ARRAY".equals( columnTypeName ) ) {
final JdbcTypeConstructor jdbcTypeConstructor = jdbcTypeRegistry.getConstructor( jdbcTypeCode ); return jdbcTypeRegistry.resolveTypeConstructorDescriptor(
if ( jdbcTypeConstructor != null ) { jdbcTypeCode,
return jdbcTypeConstructor.resolveType( jdbcTypeRegistry.getDescriptor( NUMERIC ),
jdbcTypeRegistry.getTypeConfiguration(), ColumnTypeInformation.EMPTY
this, );
jdbcTypeRegistry.getDescriptor( NUMERIC ),
ColumnTypeInformation.EMPTY
);
}
} }
break; break;
case NUMERIC: case NUMERIC:

View File

@ -40,10 +40,21 @@ public JdbcType resolveType(
JdbcType elementType, JdbcType elementType,
ColumnTypeInformation columnTypeInformation) { ColumnTypeInformation columnTypeInformation) {
// a bit wrong, since columnTypeInformation.getTypeName() is typically null! // a bit wrong, since columnTypeInformation.getTypeName() is typically null!
return new OracleNestedTableJdbcType( String typeName = columnTypeInformation == null ? null : columnTypeInformation.getTypeName();
elementType, if ( typeName == null || typeName.isBlank() ) {
columnTypeInformation == null ? null : columnTypeInformation.getTypeName() Integer precision = null;
); Integer scale = null;
if ( columnTypeInformation != null ) {
precision = columnTypeInformation.getColumnSize();
scale = columnTypeInformation.getDecimalDigits();
}
typeName = OracleArrayJdbcType.getTypeName( elementType.getJdbcRecommendedJavaTypeMapping(
precision,
scale,
typeConfiguration
), dialect );
}
return new OracleNestedTableJdbcType( elementType, typeName );
} }
@Override @Override

View File

@ -347,15 +347,13 @@ public JdbcType resolveSqlTypeDescriptor(
} }
break; break;
case ARRAY: case ARRAY:
final JdbcTypeConstructor jdbcTypeConstructor = jdbcTypeRegistry.getConstructor( jdbcTypeCode );
// PostgreSQL names array types by prepending an underscore to the base name // PostgreSQL names array types by prepending an underscore to the base name
if ( jdbcTypeConstructor != null && columnTypeName.charAt( 0 ) == '_' ) { if ( columnTypeName.charAt( 0 ) == '_' ) {
final String componentTypeName = columnTypeName.substring( 1 ); final String componentTypeName = columnTypeName.substring( 1 );
final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() ); final Integer sqlTypeCode = resolveSqlTypeCode( componentTypeName, jdbcTypeRegistry.getTypeConfiguration() );
if ( sqlTypeCode != null ) { if ( sqlTypeCode != null ) {
return jdbcTypeConstructor.resolveType( return jdbcTypeRegistry.resolveTypeConstructorDescriptor(
jdbcTypeRegistry.getTypeConfiguration(), jdbcTypeCode,
this,
jdbcTypeRegistry.getDescriptor( sqlTypeCode ), jdbcTypeRegistry.getDescriptor( sqlTypeCode ),
ColumnTypeInformation.EMPTY ColumnTypeInformation.EMPTY
); );

View File

@ -17,9 +17,7 @@
import org.hibernate.type.ConvertedBasicArrayType; import org.hibernate.type.ConvertedBasicArrayType;
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter; import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor;
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
import org.hibernate.type.internal.BasicTypeImpl; import org.hibernate.type.internal.BasicTypeImpl;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
@ -41,11 +39,9 @@ public JavaType<E> getElementJavaType() {
@Override @Override
public JdbcType getRecommendedJdbcType(JdbcTypeIndicators indicators) { public JdbcType getRecommendedJdbcType(JdbcTypeIndicators indicators) {
// Always determine the recommended type to make sure this is a valid basic java type // Always determine the recommended type to make sure this is a valid basic java type
return getArrayJdbcType( return indicators.getTypeConfiguration().getJdbcTypeRegistry().resolveTypeConstructorDescriptor(
indicators.getTypeConfiguration(),
indicators.getDialect(),
indicators.getPreferredSqlTypeCodeForArray(), indicators.getPreferredSqlTypeCodeForArray(),
new BasicTypeImpl<>( getElementJavaType(), componentJavaType.getRecommendedJdbcType( indicators ) ), new BasicTypeImpl<>( componentJavaType, componentJavaType.getRecommendedJdbcType( indicators ) ),
ColumnTypeInformation.EMPTY ColumnTypeInformation.EMPTY
); );
} }
@ -86,9 +82,7 @@ <F> BasicType<T> createTypeUsingConverter(
final JavaType<?> relationalJavaType = typeConfiguration.getJavaTypeRegistry().getDescriptor( convertedArrayClass ); final JavaType<?> relationalJavaType = typeConfiguration.getJavaTypeRegistry().getDescriptor( convertedArrayClass );
return new ConvertedBasicArrayType<>( return new ConvertedBasicArrayType<>(
elementType, elementType,
getArrayJdbcType( typeConfiguration.getJdbcTypeRegistry().resolveTypeConstructorDescriptor(
typeConfiguration,
dialect,
stdIndicators.getExplicitJdbcTypeCode(), stdIndicators.getExplicitJdbcTypeCode(),
elementType, elementType,
columnTypeInformation columnTypeInformation
@ -105,9 +99,7 @@ BasicType<T> resolveType(
BasicType<E> elementType, BasicType<E> elementType,
ColumnTypeInformation columnTypeInformation, ColumnTypeInformation columnTypeInformation,
JdbcTypeIndicators stdIndicators) { JdbcTypeIndicators stdIndicators) {
final JdbcType arrayJdbcType = getArrayJdbcType( final JdbcType arrayJdbcType = typeConfiguration.getJdbcTypeRegistry().resolveTypeConstructorDescriptor(
typeConfiguration,
dialect,
stdIndicators.getExplicitJdbcTypeCode(), stdIndicators.getExplicitJdbcTypeCode(),
elementType, elementType,
columnTypeInformation columnTypeInformation
@ -117,53 +109,6 @@ BasicType<T> resolveType(
arrayJdbcType, arrayJdbcType,
() -> new BasicArrayType<>( elementType, arrayJdbcType, arrayJavaType ) () -> new BasicArrayType<>( elementType, arrayJdbcType, arrayJavaType )
); );
// return typeConfiguration.getBasicTypeRegistry().getRegisteredType( elementType.getName() ) == elementType
// ? typeConfiguration.standardBasicTypeForJavaType(
// arrayJavaType.getJavaType(),
// javaType -> basicArrayType( typeConfiguration, dialect, elementType, columnTypeInformation, stdIndicators, arrayJavaType )
// )
// : basicArrayType( typeConfiguration, dialect, elementType, columnTypeInformation, stdIndicators, arrayJavaType );
} }
// BasicType<T> basicArrayType(
// TypeConfiguration typeConfiguration,
// Dialect dialect,
// BasicType<E> elementType,
// ColumnTypeInformation columnTypeInformation,
// JdbcTypeIndicators stdIndicators,
// JavaType<T> javaType) {
// return new BasicArrayType<>(
// elementType,
// getArrayJdbcType(
// typeConfiguration,
// dialect,
// stdIndicators.getExplicitJdbcTypeCode(),
// elementType,
// columnTypeInformation
// ),
// javaType
// );
// }
static JdbcType getArrayJdbcType(
TypeConfiguration typeConfiguration,
Dialect dialect,
int preferredSqlTypeCodeForArray,
BasicType<?> elementType,
ColumnTypeInformation columnTypeInformation) {
final JdbcTypeRegistry jdbcTypeRegistry = typeConfiguration.getJdbcTypeRegistry();
final JdbcTypeConstructor arrayJdbcTypeConstructor =
jdbcTypeRegistry.getConstructor( preferredSqlTypeCodeForArray );
if ( arrayJdbcTypeConstructor != null ) {
return arrayJdbcTypeConstructor.resolveType(
typeConfiguration,
dialect,
elementType,
columnTypeInformation
);
}
else {
return jdbcTypeRegistry.getDescriptor( preferredSqlTypeCodeForArray );
}
}
} }

View File

@ -10,11 +10,9 @@
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.function.Function;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.Incubating; import org.hibernate.Incubating;
@ -27,7 +25,6 @@
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.CollectionClassification; import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation; import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
import org.hibernate.type.BasicArrayType;
import org.hibernate.type.BasicCollectionType; import org.hibernate.type.BasicCollectionType;
import org.hibernate.type.BasicPluralType; import org.hibernate.type.BasicPluralType;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
@ -40,9 +37,7 @@
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.MutabilityPlan; import org.hibernate.type.descriptor.java.MutabilityPlan;
import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor;
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
import org.hibernate.type.internal.BasicTypeImpl; import org.hibernate.type.internal.BasicTypeImpl;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
@ -73,11 +68,9 @@ public JavaType<E> getElementJavaType() {
public JdbcType getRecommendedJdbcType(JdbcTypeIndicators indicators) { public JdbcType getRecommendedJdbcType(JdbcTypeIndicators indicators) {
// Always determine the recommended type to make sure this is a valid basic java type // Always determine the recommended type to make sure this is a valid basic java type
// (even though we only use this inside the if block, we want it to throw here if something wrong) // (even though we only use this inside the if block, we want it to throw here if something wrong)
return getArrayJdbcType( return indicators.getTypeConfiguration().getJdbcTypeRegistry().resolveTypeConstructorDescriptor(
indicators.getTypeConfiguration(),
indicators.getDialect(),
indicators.getPreferredSqlTypeCodeForArray(), indicators.getPreferredSqlTypeCodeForArray(),
new BasicTypeImpl<>( getElementJavaType(), componentJavaType.getRecommendedJdbcType( indicators ) ), new BasicTypeImpl<>( componentJavaType, componentJavaType.getRecommendedJdbcType( indicators ) ),
ColumnTypeInformation.EMPTY ColumnTypeInformation.EMPTY
); );
} }
@ -119,23 +112,11 @@ public BasicType<?> resolveType(
} }
final BasicValueConverter<E, ?> valueConverter = elementType.getValueConverter(); final BasicValueConverter<E, ?> valueConverter = elementType.getValueConverter();
if ( valueConverter == null ) { if ( valueConverter == null ) {
final JdbcType arrayJdbcType = getArrayJdbcType( final JdbcType arrayJdbcType = typeConfiguration.getJdbcTypeRegistry().resolveTypeConstructorDescriptor(
typeConfiguration,
dialect,
stdIndicators.getPreferredSqlTypeCodeForArray(), stdIndicators.getPreferredSqlTypeCodeForArray(),
elementType, elementType,
columnTypeInformation columnTypeInformation
); );
final Function<JavaType<Object>, BasicType<Object>> creator = javaType -> {
//noinspection unchecked,rawtypes
return new BasicCollectionType( elementType, arrayJdbcType, collectionJavaType );
};
// if ( typeConfiguration.getBasicTypeRegistry().getRegisteredType( elementType.getName() ) == elementType ) {
// return typeConfiguration.standardBasicTypeForJavaType( collectionJavaType.getJavaType(), creator );
// }
// //noinspection unchecked
// return creator.apply( (JavaType<Object>) (JavaType<?>) collectionJavaType );
return typeConfiguration.getBasicTypeRegistry().resolve( return typeConfiguration.getBasicTypeRegistry().resolve(
collectionJavaType, collectionJavaType,
arrayJdbcType, arrayJdbcType,
@ -149,9 +130,7 @@ public BasicType<?> resolveType(
//noinspection unchecked,rawtypes //noinspection unchecked,rawtypes
return new ConvertedBasicCollectionType( return new ConvertedBasicCollectionType(
elementType, elementType,
getArrayJdbcType( typeConfiguration.getJdbcTypeRegistry().resolveTypeConstructorDescriptor(
typeConfiguration,
dialect,
stdIndicators.getPreferredSqlTypeCodeForArray(), stdIndicators.getPreferredSqlTypeCodeForArray(),
elementType, elementType,
columnTypeInformation columnTypeInformation
@ -162,29 +141,6 @@ public BasicType<?> resolveType(
} }
} }
//TODO: copy/pasted from AbstractArrayJavaType
private static JdbcType getArrayJdbcType(
TypeConfiguration typeConfiguration,
Dialect dialect,
int preferredSqlTypeCodeForArray,
BasicType<?> elementType,
ColumnTypeInformation columnTypeInformation) {
final JdbcTypeRegistry jdbcTypeRegistry = typeConfiguration.getJdbcTypeRegistry();
final JdbcTypeConstructor arrayJdbcTypeConstructor =
jdbcTypeRegistry.getConstructor( preferredSqlTypeCodeForArray );
if ( arrayJdbcTypeConstructor != null ) {
return arrayJdbcTypeConstructor.resolveType(
typeConfiguration,
dialect,
elementType,
columnTypeInformation
);
}
else {
return jdbcTypeRegistry.getDescriptor( preferredSqlTypeCodeForArray );
}
}
@Override @Override
public String extractLoggableRepresentation(C value) { public String extractLoggableRepresentation(C value) {
if ( value == null ) { if ( value == null ) {

View File

@ -214,11 +214,11 @@ public String toString() {
public boolean equals(Object o) { public boolean equals(Object o) {
return o != null && return o != null &&
getClass() == o.getClass() && getClass() == o.getClass() &&
getElementJdbcType().equals( ((ArrayJdbcType) o).getElementJdbcType() ); getElementJdbcType().equals( ( (ArrayJdbcType) o ).getElementJdbcType() );
} }
@Override @Override
public int hashCode() { public int hashCode() {
return getJdbcTypeCode() + getElementJdbcType().hashCode(); return getJdbcTypeCode() + 31 * getElementJdbcType().hashCode();
} }
} }

View File

@ -7,13 +7,20 @@
package org.hibernate.type.descriptor.jdbc.spi; package org.hibernate.type.descriptor.jdbc.spi;
import java.io.Serializable; import java.io.Serializable;
import java.sql.Types;
import java.util.Locale; import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.hibernate.boot.model.TruthValue;
import org.hibernate.dialect.Dialect;
import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.JdbcTypeNameMapper; import org.hibernate.type.descriptor.JdbcTypeNameMapper;
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType; import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
import org.hibernate.type.descriptor.jdbc.ArrayJdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor; import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor;
import org.hibernate.type.descriptor.jdbc.JdbcTypeFamilyInformation; import org.hibernate.type.descriptor.jdbc.JdbcTypeFamilyInformation;
@ -23,6 +30,8 @@
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;
/** /**
* A registry mapping {@link org.hibernate.type.SqlTypes JDBC type codes} * A registry mapping {@link org.hibernate.type.SqlTypes JDBC type codes}
* to implementations of the {@link JdbcType} interface. * to implementations of the {@link JdbcType} interface.
@ -39,6 +48,13 @@ public class JdbcTypeRegistry implements JdbcTypeBaseline.BaselineTarget, Serial
private final ConcurrentHashMap<Integer, JdbcType> descriptorMap = new ConcurrentHashMap<>(); private final ConcurrentHashMap<Integer, JdbcType> descriptorMap = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Integer, JdbcTypeConstructor> descriptorConstructorMap = new ConcurrentHashMap<>(); private final ConcurrentHashMap<Integer, JdbcTypeConstructor> descriptorConstructorMap = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, AggregateJdbcType> aggregateDescriptorMap = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String, AggregateJdbcType> aggregateDescriptorMap = new ConcurrentHashMap<>();
/**
* A registry for storing the constructed {@link JdbcType} for both
* {@link JdbcTypeConstructor#resolveType(TypeConfiguration, Dialect, JdbcType, ColumnTypeInformation)} and
* {@link JdbcTypeConstructor#resolveType(TypeConfiguration, Dialect, BasicType, ColumnTypeInformation)} in a single
* map.
*/
private final ConcurrentHashMap<TypeConstructedJdbcTypeKey, JdbcType> typeConstructorDescriptorMap = new ConcurrentHashMap<>();
public JdbcTypeRegistry(TypeConfiguration typeConfiguration) { public JdbcTypeRegistry(TypeConfiguration typeConfiguration) {
this.typeConfiguration = typeConfiguration; this.typeConfiguration = typeConfiguration;
@ -174,6 +190,68 @@ public AggregateJdbcType findAggregateDescriptor(String typeName) {
return aggregateDescriptorMap.get( typeName.toLowerCase( Locale.ROOT ) ); return aggregateDescriptorMap.get( typeName.toLowerCase( Locale.ROOT ) );
} }
/**
* Construct a {@link JdbcType} via {@link JdbcTypeConstructor#resolveType(TypeConfiguration, Dialect, BasicType, ColumnTypeInformation)}
* or return a compatible one from this registry.
*/
public JdbcType resolveTypeConstructorDescriptor(
int jdbcTypeConstructorCode,
BasicType<?> elementType,
@Nullable ColumnTypeInformation columnTypeInformation) {
return resolveTypeConstructorDescriptor( jdbcTypeConstructorCode, (Object) elementType, columnTypeInformation );
}
/**
* Construct a {@link JdbcType} via {@link JdbcTypeConstructor#resolveType(TypeConfiguration, Dialect, JdbcType, ColumnTypeInformation)}
* or return a compatible one from this registry.
*/
public JdbcType resolveTypeConstructorDescriptor(
int jdbcTypeConstructorCode,
JdbcType elementType,
@Nullable ColumnTypeInformation columnTypeInformation) {
return resolveTypeConstructorDescriptor( jdbcTypeConstructorCode, (Object) elementType, columnTypeInformation );
}
private JdbcType resolveTypeConstructorDescriptor(
int jdbcTypeConstructorCode,
Object elementType,
@Nullable ColumnTypeInformation columnTypeInformation) {
final TypeConstructedJdbcTypeKey key = new TypeConstructedJdbcTypeKey(
jdbcTypeConstructorCode,
elementType,
columnTypeInformation
);
final JdbcType descriptor = typeConstructorDescriptorMap.get( key );
if ( descriptor != null ) {
return descriptor;
}
final JdbcTypeConstructor jdbcTypeConstructor = getConstructor( jdbcTypeConstructorCode );
if ( jdbcTypeConstructor != null ) {
final JdbcType jdbcType;
if ( elementType instanceof BasicType<?> ) {
jdbcType = jdbcTypeConstructor.resolveType(
typeConfiguration,
typeConfiguration.getCurrentBaseSqlTypeIndicators().getDialect(),
(BasicType<?>) elementType,
columnTypeInformation
);
}
else {
jdbcType = jdbcTypeConstructor.resolveType(
typeConfiguration,
typeConfiguration.getCurrentBaseSqlTypeIndicators().getDialect(),
(JdbcType) elementType,
columnTypeInformation
);
}
final JdbcType existingType = typeConstructorDescriptorMap.putIfAbsent( key, jdbcType );
return existingType != null ? existingType : jdbcType;
}
else {
return getDescriptor( jdbcTypeConstructorCode );
}
}
public boolean hasRegisteredDescriptor(int jdbcTypeCode) { public boolean hasRegisteredDescriptor(int jdbcTypeCode) {
return descriptorMap.containsKey( jdbcTypeCode ) return descriptorMap.containsKey( jdbcTypeCode )
|| JdbcTypeNameMapper.isStandardTypeCode( jdbcTypeCode ) || JdbcTypeNameMapper.isStandardTypeCode( jdbcTypeCode )
@ -191,4 +269,80 @@ public void addTypeConstructor(int jdbcTypeCode, JdbcTypeConstructor jdbcTypeCon
public void addTypeConstructor(JdbcTypeConstructor jdbcTypeConstructor) { public void addTypeConstructor(JdbcTypeConstructor jdbcTypeConstructor) {
addTypeConstructor( jdbcTypeConstructor.getDefaultSqlTypeCode(), jdbcTypeConstructor ); addTypeConstructor( jdbcTypeConstructor.getDefaultSqlTypeCode(), jdbcTypeConstructor );
} }
private static final class TypeConstructedJdbcTypeKey {
private final int typeConstructorTypeCode;
private final Object jdbcTypeOrBasicType;
private final TruthValue nullable;
private final int typeCode;
private final @Nullable String typeName;
private final int columnSize;
private final int decimalDigits;
public TypeConstructedJdbcTypeKey(
int typeConstructorTypeCode,
Object jdbcTypeOrBasicType,
@Nullable ColumnTypeInformation columnTypeInformation) {
this.typeConstructorTypeCode = typeConstructorTypeCode;
this.jdbcTypeOrBasicType = jdbcTypeOrBasicType;
if ( columnTypeInformation == null ) {
this.nullable = TruthValue.UNKNOWN;
this.typeCode = Types.OTHER;
this.typeName = null;
this.columnSize = 0;
this.decimalDigits = 0;
}
else {
this.nullable = columnTypeInformation.getNullable();
this.typeCode = columnTypeInformation.getTypeCode();
this.typeName = columnTypeInformation.getTypeName();
this.columnSize = columnTypeInformation.getColumnSize();
this.decimalDigits = columnTypeInformation.getDecimalDigits();
}
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
TypeConstructedJdbcTypeKey that = (TypeConstructedJdbcTypeKey) o;
if ( typeConstructorTypeCode != that.typeConstructorTypeCode ) {
return false;
}
if ( typeCode != that.typeCode ) {
return false;
}
if ( columnSize != that.columnSize ) {
return false;
}
if ( decimalDigits != that.decimalDigits ) {
return false;
}
if ( !jdbcTypeOrBasicType.equals( that.jdbcTypeOrBasicType ) ) {
return false;
}
if ( nullable != that.nullable ) {
return false;
}
return Objects.equals( typeName, that.typeName );
}
@Override
public int hashCode() {
int result = typeConstructorTypeCode;
result = 31 * result + jdbcTypeOrBasicType.hashCode();
result = 31 * result + ( nullable != null ? nullable.hashCode() : 0 );
result = 31 * result + typeCode;
result = 31 * result + ( typeName != null ? typeName.hashCode() : 0 );
result = 31 * result + columnSize;
result = 31 * result + decimalDigits;
return result;
}
}
} }