From 400a4bc24ef9bfcd92e526654c4a181c6ceb1454 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Mon, 27 Nov 2017 11:11:59 -0600 Subject: [PATCH] HHH-12115 - No Dialect mapping for JDBC type: 1899073220 in Wildfly (AttributeConverter and Short) Improved JavaDocs pointing to the exact parts of the JDBC spec that the JdbcTypeJavaClassMappings mappings come from; Added mapping for BigInteger as well --- .../sql/JdbcTypeJavaClassMappings.java | 130 ++++++++++++------ 1 file changed, 90 insertions(+), 40 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/JdbcTypeJavaClassMappings.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/JdbcTypeJavaClassMappings.java index b0a3bb885b..febd37218e 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/JdbcTypeJavaClassMappings.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/JdbcTypeJavaClassMappings.java @@ -7,15 +7,18 @@ package org.hibernate.type.descriptor.sql; import java.math.BigDecimal; +import java.math.BigInteger; import java.sql.Blob; import java.sql.Clob; +import java.sql.NClob; import java.sql.Ref; +import java.sql.RowId; +import java.sql.SQLXML; import java.sql.Struct; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; import java.util.Calendar; -import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.hibernate.mapping.Array; @@ -23,15 +26,15 @@ import org.jboss.logging.Logger; /** - * Presents recommended {@literal JDCB typecode <-> Java Class} mappings. Currently the mappings contained here come - * from the recommendations defined by the JDBC spec itself, as outlined at - * . - *

+ * Maintains the JDBC recommended mappings for JDBC type-code to/from Java Class + * as defined in _Appendix B : Data Type Conversion Tables_ of the _JDBC 4.0 Specification_ + * * Eventually, the plan is to have {@link org.hibernate.dialect.Dialect} and * {@link java.sql.DatabaseMetaData#getTypeInfo()} contribute this information. * * @author Steve Ebersole */ +@SuppressWarnings("WeakerAccess") public class JdbcTypeJavaClassMappings { private static final Logger log = Logger.getLogger( JdbcTypeJavaClassMappings.class ); @@ -41,10 +44,17 @@ public class JdbcTypeJavaClassMappings { private final ConcurrentHashMap jdbcTypeCodeToJavaClassMap; private JdbcTypeJavaClassMappings() { - javaClassToJdbcTypeCodeMap = buildJdbcJavaClassMappings(); - jdbcTypeCodeToJavaClassMap = transpose( javaClassToJdbcTypeCodeMap ); + javaClassToJdbcTypeCodeMap = buildJavaClassToJdbcTypeCodeMappings(); + jdbcTypeCodeToJavaClassMap = buildJdbcTypeCodeToJavaClassMappings(); } + /** + * For the given Java type, determine the JDBC recommended JDBC type. + * + * This includes the mappings defined in TABLE B-2 - Java Types Mapped to JDBC Types + * as well as some additional "common sense" mappings for things like BigDecimal, BigInteger, + * etc. + */ public int determineJdbcTypeCodeForJavaClass(Class cls) { Integer typeCode = javaClassToJdbcTypeCodeMap.get( cls ); if ( typeCode != null ) { @@ -58,6 +68,10 @@ public int determineJdbcTypeCodeForJavaClass(Class cls) { return specialCode; } + /** + * For the given JDBC type, determine the JDBC recommended Java type. These mappings + * are defined by TABLE B-1 - JDBC Types Mapped to Java Types + */ public Class determineJavaClassForJdbcTypeCode(Integer typeCode) { Class cls = jdbcTypeCodeToJavaClassMap.get( typeCode ); if ( cls != null ) { @@ -71,6 +85,9 @@ public Class determineJavaClassForJdbcTypeCode(Integer typeCode) { return Object.class; } + /** + * @see #determineJavaClassForJdbcTypeCode(Integer) + */ public Class determineJavaClassForJdbcTypeCode(int typeCode) { return determineJavaClassForJdbcTypeCode( Integer.valueOf( typeCode ) ); } @@ -78,47 +95,80 @@ public Class determineJavaClassForJdbcTypeCode(int typeCode) { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - private static ConcurrentHashMap buildJdbcJavaClassMappings() { - ConcurrentHashMap jdbcJavaClassMappings = new ConcurrentHashMap(); + private static ConcurrentHashMap buildJavaClassToJdbcTypeCodeMappings() { + final ConcurrentHashMap workMap = new ConcurrentHashMap<>(); // these mappings are the ones outlined specifically in the spec - jdbcJavaClassMappings.put( String.class, Types.VARCHAR ); - jdbcJavaClassMappings.put( BigDecimal.class, Types.NUMERIC ); - jdbcJavaClassMappings.put( Boolean.class, Types.BIT ); - jdbcJavaClassMappings.put( Short.class, Types.SMALLINT ); - jdbcJavaClassMappings.put( Integer.class, Types.INTEGER ); - jdbcJavaClassMappings.put( Long.class, Types.BIGINT ); - jdbcJavaClassMappings.put( Float.class, Types.REAL ); - jdbcJavaClassMappings.put( Double.class, Types.DOUBLE ); - jdbcJavaClassMappings.put( byte[].class, Types.LONGVARBINARY ); - jdbcJavaClassMappings.put( java.sql.Date.class, Types.DATE ); - jdbcJavaClassMappings.put( Time.class, Types.TIME ); - jdbcJavaClassMappings.put( Timestamp.class, Types.TIMESTAMP ); - jdbcJavaClassMappings.put( Blob.class, Types.BLOB ); - jdbcJavaClassMappings.put( Clob.class, Types.CLOB ); - jdbcJavaClassMappings.put( Array.class, Types.ARRAY ); - jdbcJavaClassMappings.put( Struct.class, Types.STRUCT ); - jdbcJavaClassMappings.put( Ref.class, Types.REF ); - jdbcJavaClassMappings.put( Class.class, Types.JAVA_OBJECT ); + workMap.put( String.class, Types.VARCHAR ); + workMap.put( BigDecimal.class, Types.NUMERIC ); + workMap.put( BigInteger.class, Types.NUMERIC ); + workMap.put( Boolean.class, Types.BIT ); + workMap.put( Short.class, Types.SMALLINT ); + workMap.put( Integer.class, Types.INTEGER ); + workMap.put( Long.class, Types.BIGINT ); + workMap.put( Float.class, Types.REAL ); + workMap.put( Double.class, Types.DOUBLE ); + workMap.put( byte[].class, Types.LONGVARBINARY ); + workMap.put( java.sql.Date.class, Types.DATE ); + workMap.put( Time.class, Types.TIME ); + workMap.put( Timestamp.class, Types.TIMESTAMP ); + workMap.put( Blob.class, Types.BLOB ); + workMap.put( Clob.class, Types.CLOB ); + workMap.put( Array.class, Types.ARRAY ); + workMap.put( Struct.class, Types.STRUCT ); + workMap.put( Ref.class, Types.REF ); + workMap.put( Class.class, Types.JAVA_OBJECT ); + workMap.put( RowId.class, Types.ROWID ); + workMap.put( SQLXML.class, Types.SQLXML ); + // additional "common sense" registrations - jdbcJavaClassMappings.put( Character.class, Types.CHAR ); - jdbcJavaClassMappings.put( char[].class, Types.VARCHAR ); - jdbcJavaClassMappings.put( Character[].class, Types.VARCHAR ); - jdbcJavaClassMappings.put( Byte[].class, Types.LONGVARBINARY ); - jdbcJavaClassMappings.put( java.util.Date.class, Types.TIMESTAMP ); - jdbcJavaClassMappings.put( Calendar.class, Types.TIMESTAMP ); + workMap.put( Character.class, Types.CHAR ); + workMap.put( char[].class, Types.VARCHAR ); + workMap.put( Character[].class, Types.VARCHAR ); + workMap.put( Byte[].class, Types.LONGVARBINARY ); + workMap.put( java.util.Date.class, Types.TIMESTAMP ); + workMap.put( Calendar.class, Types.TIMESTAMP ); - return jdbcJavaClassMappings; + return workMap; } - private static ConcurrentHashMap transpose(ConcurrentHashMap javaClassToJdbcTypeCodeMap) { - final ConcurrentHashMap transposed = new ConcurrentHashMap(); + private static ConcurrentHashMap buildJdbcTypeCodeToJavaClassMappings() { + final ConcurrentHashMap workMap = new ConcurrentHashMap<>(); - for ( Map.Entry entry : javaClassToJdbcTypeCodeMap.entrySet() ) { - transposed.put( entry.getValue(), entry.getKey() ); - } + workMap.put( Types.CHAR, String.class ); + workMap.put( Types.VARCHAR, String.class ); + workMap.put( Types.LONGVARCHAR, String.class ); + workMap.put( Types.NCHAR, String.class ); + workMap.put( Types.NVARCHAR, String.class ); + workMap.put( Types.LONGNVARCHAR, String.class ); + workMap.put( Types.NUMERIC, BigDecimal.class ); + workMap.put( Types.DECIMAL, BigDecimal.class ); + workMap.put( Types.BIT, Boolean.class ); + workMap.put( Types.BOOLEAN, Boolean.class ); + workMap.put( Types.TINYINT, Byte.class ); + workMap.put( Types.SMALLINT, Short.class ); + workMap.put( Types.INTEGER, Integer.class ); + workMap.put( Types.BIGINT, Long.class ); + workMap.put( Types.REAL, Float.class ); + workMap.put( Types.DOUBLE, Double.class ); + workMap.put( Types.FLOAT, Double.class ); + workMap.put( Types.BINARY, byte[].class ); + workMap.put( Types.VARBINARY, byte[].class ); + workMap.put( Types.LONGVARBINARY, byte[].class ); + workMap.put( Types.DATE, java.sql.Date.class ); + workMap.put( Types.TIME, Time.class ); + workMap.put( Types.TIMESTAMP, Timestamp.class ); + workMap.put( Types.BLOB, Blob.class ); + workMap.put( Types.CLOB, Clob.class ); + workMap.put( Types.NCLOB, NClob.class ); + workMap.put( Types.ARRAY, Array.class ); + workMap.put( Types.STRUCT, Struct.class ); + workMap.put( Types.REF, Ref.class ); + workMap.put( Types.JAVA_OBJECT, Class.class ); + workMap.put( Types.ROWID, RowId.class ); + workMap.put( Types.SQLXML, SQLXML.class ); - return transposed; + return workMap; } }