Add support for specifying the SqlTypes field name when a type code is expected
This commit is contained in:
parent
e1742ac3ac
commit
b4a1b149fb
|
@ -382,9 +382,11 @@ This setting applies to Oracle Dialect only, and it specifies whether `byte[]` o
|
|||
|
||||
`*hibernate.type.preferred_boolean_jdbc_type_code*` (e.g. `-7` for `java.sql.Types.BIT`)::
|
||||
Global setting identifying the preferred JDBC type code for storing boolean values. The fallback is to ask the Dialect.
|
||||
Can also specify the name of the constant in `org.hibernate.type.SqlTypes` instead.
|
||||
|
||||
`*hibernate.type.preferred_duration_jdbc_type_code*` (e.g. `2` for `java.sql.Types.NUMERIC` or `3100` for `org.hibernate.types.SqlTypes.INTERVAL_SECOND` (default value))::
|
||||
Global setting identifying the preferred JDBC type code for storing duration values.
|
||||
Can also specify the name of the constant in `org.hibernate.type.SqlTypes` instead.
|
||||
|
||||
==== Bean Validation options
|
||||
`*jakarta.persistence.validation.factory*` (e.g. `jakarta.validation.ValidationFactory` implementation)::
|
||||
|
|
|
@ -38,8 +38,7 @@ import static org.hamcrest.Matchers.is;
|
|||
*/
|
||||
@DomainModel(annotatedClasses = DurationMappingLegacyTests.EntityWithDuration.class)
|
||||
@SessionFactory
|
||||
// 2 stands for the type code Types.NUMERIC
|
||||
@ServiceRegistry(settings = @Setting(name = AvailableSettings.PREFERRED_DURATION_JDBC_TYPE_CODE, value = "2"))
|
||||
@ServiceRegistry(settings = @Setting(name = AvailableSettings.PREFERRED_DURATION_JDBC_TYPE_CODE, value = "NUMERIC"))
|
||||
public class DurationMappingLegacyTests {
|
||||
|
||||
@Test
|
||||
|
|
|
@ -2479,6 +2479,8 @@ public interface AvailableSettings {
|
|||
* {@link org.hibernate.dialect.Dialect#getPreferredSqlTypeCodeForBoolean()
|
||||
* dialect-specific default type code} is used.
|
||||
*
|
||||
* Can also specify the name of the constant in {@link org.hibernate.type.SqlTypes} instead.
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
String PREFERRED_BOOLEAN_JDBC_TYPE_CODE = "hibernate.type.preferred_boolean_jdbc_type_code";
|
||||
|
@ -2487,6 +2489,8 @@ public interface AvailableSettings {
|
|||
* Specifies the preferred JDBC type code for storing duration values. When no
|
||||
* type code is explicitly specified, {@link org.hibernate.type.SqlTypes#INTERVAL_SECOND} is used.
|
||||
*
|
||||
* Can also specify the name of the constant in {@link org.hibernate.type.SqlTypes} instead.
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
String PREFERRED_DURATION_JDBC_TYPE_CODE = "hibernate.type.preferred_duration_jdbc_type_code";
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.engine.jdbc.spi.JdbcServices;
|
|||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.JdbcTypeNameMapper;
|
||||
|
||||
/**
|
||||
* Collection of helper methods for dealing with configuration settings.
|
||||
|
@ -516,7 +517,7 @@ public final class ConfigurationHelper {
|
|||
public static synchronized int getPreferredSqlTypeCodeForBoolean(StandardServiceRegistry serviceRegistry) {
|
||||
final Integer typeCode = serviceRegistry.getService( ConfigurationService.class ).getSetting(
|
||||
AvailableSettings.PREFERRED_BOOLEAN_JDBC_TYPE_CODE,
|
||||
StandardConverters.INTEGER
|
||||
TypeCodeConverter.INSTANCE
|
||||
);
|
||||
if ( typeCode != null ) {
|
||||
return typeCode;
|
||||
|
@ -532,9 +533,31 @@ public final class ConfigurationHelper {
|
|||
public static synchronized int getPreferredSqlTypeCodeForDuration(StandardServiceRegistry serviceRegistry) {
|
||||
return serviceRegistry.getService( ConfigurationService.class ).getSetting(
|
||||
AvailableSettings.PREFERRED_DURATION_JDBC_TYPE_CODE,
|
||||
StandardConverters.INTEGER,
|
||||
TypeCodeConverter.INSTANCE,
|
||||
SqlTypes.INTERVAL_SECOND
|
||||
);
|
||||
}
|
||||
|
||||
private static class TypeCodeConverter implements ConfigurationService.Converter<Integer> {
|
||||
|
||||
public static final TypeCodeConverter INSTANCE = new TypeCodeConverter();
|
||||
|
||||
@Override
|
||||
public Integer convert(Object value) {
|
||||
if ( value == null ) {
|
||||
throw new IllegalArgumentException( "Null value passed to convert" );
|
||||
}
|
||||
|
||||
if ( value instanceof Number ) {
|
||||
return ( (Number) value ).intValue();
|
||||
}
|
||||
|
||||
final String string = value.toString();
|
||||
final Integer typeCode = JdbcTypeNameMapper.getTypeCode( string );
|
||||
if ( typeCode != null ) {
|
||||
return typeCode;
|
||||
}
|
||||
return Integer.parseInt( string );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,16 +26,14 @@ import static org.hibernate.internal.CoreLogging.messageLogger;
|
|||
public final class JdbcTypeNameMapper {
|
||||
private static final CoreMessageLogger LOG = messageLogger( JdbcTypeNameMapper.class );
|
||||
|
||||
private static final Map<Integer,String> JDBC_TYPE_MAP = buildJdbcTypeMap( Types.class );
|
||||
private static final Map<Integer,String> SQL_TYPE_MAP = buildJdbcTypeMap( SqlTypes.class );
|
||||
private static final Map<Integer, String> JDBC_TYPE_MAP = buildJdbcTypeMap( Types.class );
|
||||
private static final Map<Integer, String> SQL_TYPE_MAP = buildJdbcTypeMap( SqlTypes.class );
|
||||
private static final Map<String, Integer> JDBC_TYPE_NAME_MAP = buildJdbcTypeNameMap( Types.class );
|
||||
private static final Map<String, Integer> SQL_TYPE_NAME_MAP = buildJdbcTypeNameMap( SqlTypes.class );
|
||||
|
||||
private static Map<Integer, String> buildJdbcTypeMap(Class<?> typesClass) {
|
||||
HashMap<Integer, String> map = new HashMap<>();
|
||||
Field[] fields = typesClass.getFields();
|
||||
if ( fields == null ) {
|
||||
throw new HibernateException( "Unexpected problem extracting JDBC type mapping codes from java.sql.Types" );
|
||||
}
|
||||
for ( Field field : fields ) {
|
||||
for ( Field field : typesClass.getFields() ) {
|
||||
try {
|
||||
final int code = field.getInt( null );
|
||||
String old = map.put( code, field.getName() );
|
||||
|
@ -50,6 +48,20 @@ public final class JdbcTypeNameMapper {
|
|||
return Collections.unmodifiableMap( map );
|
||||
}
|
||||
|
||||
private static Map<String, Integer> buildJdbcTypeNameMap(Class<?> typesClass) {
|
||||
HashMap<String, Integer> map = new HashMap<>();
|
||||
for ( Field field : typesClass.getFields() ) {
|
||||
try {
|
||||
final int code = field.getInt( null );
|
||||
map.put( field.getName(), code );
|
||||
}
|
||||
catch ( IllegalAccessException e ) {
|
||||
throw new HibernateException( "Unable to access JDBC type mapping [" + field.getName() + "]", e );
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableMap( map );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given JDBC type code represents a standard JDBC type ("standard" being those defined on
|
||||
* {@link java.sql.Types}).
|
||||
|
@ -91,6 +103,18 @@ public final class JdbcTypeNameMapper {
|
|||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type code as in the static field names defined on {@link java.sql.Types}. If a type name is not
|
||||
* recognized, <code>null</code> is returned.
|
||||
*
|
||||
* @param typeName The type name to find the code for.
|
||||
*
|
||||
* @return The type code.
|
||||
*/
|
||||
public static Integer getTypeCode(String typeName) {
|
||||
return SQL_TYPE_NAME_MAP.get( typeName );
|
||||
}
|
||||
|
||||
private JdbcTypeNameMapper() {
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue