diff --git a/pom.xml b/pom.xml index 2c64717780..591db97aca 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-relational-parent - 2.4.0-SNAPSHOT + 2.4.0-1089-sql-type-SNAPSHOT pom Spring Data Relational Parent diff --git a/spring-data-jdbc-distribution/pom.xml b/spring-data-jdbc-distribution/pom.xml index 0646c2846d..78f1788fe2 100644 --- a/spring-data-jdbc-distribution/pom.xml +++ b/spring-data-jdbc-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-relational-parent - 2.4.0-SNAPSHOT + 2.4.0-1089-sql-type-SNAPSHOT ../pom.xml diff --git a/spring-data-jdbc/pom.xml b/spring-data-jdbc/pom.xml index 11114a795e..9bea548bf9 100644 --- a/spring-data-jdbc/pom.xml +++ b/spring-data-jdbc/pom.xml @@ -6,7 +6,7 @@ 4.0.0 spring-data-jdbc - 2.4.0-SNAPSHOT + 2.4.0-1089-sql-type-SNAPSHOT Spring Data JDBC Spring Data module for JDBC repositories. @@ -15,7 +15,7 @@ org.springframework.data spring-data-relational-parent - 2.4.0-SNAPSHOT + 2.4.0-1089-sql-type-SNAPSHOT diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverter.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverter.java index 312eb8bab2..1d076d0e6e 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverter.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverter.java @@ -19,6 +19,7 @@ import java.sql.JDBCType; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.SQLType; import java.util.Map; import java.util.Optional; @@ -170,10 +171,15 @@ private Class getReferenceColumnType(RelationalPersistentProperty property) { * @see org.springframework.data.jdbc.core.convert.JdbcConverter#getSqlType(org.springframework.data.relational.core.mapping.RelationalPersistentProperty) */ @Override + public SQLType getTargetSqlType(RelationalPersistentProperty property) { + return JdbcUtil.targetSqlTypeFor(getColumnType(property)); + } + + @Override + @Deprecated public int getSqlType(RelationalPersistentProperty property) { return JdbcUtil.sqlTypeFor(getColumnType(property)); } - /* * (non-Javadoc) * @see org.springframework.data.jdbc.core.convert.JdbcConverter#getColumnType(org.springframework.data.relational.core.mapping.RelationalPersistentProperty) @@ -282,12 +288,19 @@ private boolean canWriteAsJdbcValue(@Nullable Object value) { return customWriteTarget.isPresent() && customWriteTarget.get().isAssignableFrom(JdbcValue.class); } - /* + @Override + @Deprecated + public JdbcValue writeJdbcValue(@Nullable Object value, Class columnType, int sqlType) { + return writeJdbcValue(value, columnType, JdbcUtil.jdbcTypeFor(sqlType)); + } + + + /* * (non-Javadoc) * @see org.springframework.data.jdbc.core.convert.JdbcConverter#writeValue(java.lang.Object, java.lang.Class, int) */ @Override - public JdbcValue writeJdbcValue(@Nullable Object value, Class columnType, int sqlType) { + public JdbcValue writeJdbcValue(@Nullable Object value, Class columnType, SQLType sqlType) { JdbcValue jdbcValue = tryToConvertToJdbcValue(value); if (jdbcValue != null) { @@ -297,7 +310,8 @@ public JdbcValue writeJdbcValue(@Nullable Object value, Class columnType, int Object convertedValue = writeValue(value, ClassTypeInformation.from(columnType)); if (convertedValue == null || !convertedValue.getClass().isArray()) { - return JdbcValue.of(convertedValue, JdbcUtil.jdbcTypeFor(sqlType)); + + return JdbcValue.of(convertedValue, sqlType); } Class componentType = convertedValue.getClass().getComponentType(); diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultDataAccessStrategy.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultDataAccessStrategy.java index a5f1eab953..151c77027a 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultDataAccessStrategy.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultDataAccessStrategy.java @@ -17,8 +17,8 @@ import static org.springframework.data.jdbc.core.convert.SqlGenerator.*; -import java.sql.JDBCType; import java.sql.ResultSet; +import java.sql.SQLType; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -546,17 +546,17 @@ private IdentifierProcessing getIdentifierProcessing() { private void addConvertedPropertyValue(SqlIdentifierParameterSource parameterSource, RelationalPersistentProperty property, @Nullable Object value, SqlIdentifier name) { - addConvertedValue(parameterSource, value, name, converter.getColumnType(property), converter.getSqlType(property)); + addConvertedValue(parameterSource, value, name, converter.getColumnType(property), converter.getTargetSqlType(property)); } private void addConvertedPropertyValue(SqlIdentifierParameterSource parameterSource, SqlIdentifier name, Object value, Class javaType) { - addConvertedValue(parameterSource, value, name, javaType, JdbcUtil.sqlTypeFor(javaType)); + addConvertedValue(parameterSource, value, name, javaType, JdbcUtil.targetSqlTypeFor(javaType)); } private void addConvertedValue(SqlIdentifierParameterSource parameterSource, @Nullable Object value, - SqlIdentifier paramName, Class javaType, int sqlType) { + SqlIdentifier paramName, Class javaType, SQLType sqlType) { JdbcValue jdbcValue = converter.writeJdbcValue( // value, // @@ -567,7 +567,7 @@ private void addConvertedValue(SqlIdentifierParameterSource parameterSource, @Nu parameterSource.addValue( // paramName, // jdbcValue.getValue(), // - JdbcUtil.sqlTypeFor(jdbcValue.getJdbcType())); + jdbcValue.getJdbcType().getVendorTypeNumber()); } private void addConvertedPropertyValuesAsList(SqlIdentifierParameterSource parameterSource, @@ -578,7 +578,7 @@ private void addConvertedPropertyValuesAsList(SqlIdentifierParameterSource param for (Object id : values) { Class columnType = converter.getColumnType(property); - int sqlType = converter.getSqlType(property); + SQLType sqlType = converter.getTargetSqlType(property); jdbcValue = converter.writeJdbcValue(id, columnType, sqlType); convertedIds.add(jdbcValue.getValue()); @@ -586,7 +586,7 @@ private void addConvertedPropertyValuesAsList(SqlIdentifierParameterSource param Assert.state(jdbcValue != null, "JdbcValue must be not null at this point. Please report this as a bug."); - JDBCType jdbcType = jdbcValue.getJdbcType(); + SQLType jdbcType = jdbcValue.getJdbcType(); int typeNumber = jdbcType == null ? JdbcUtils.TYPE_UNKNOWN : jdbcType.getVendorTypeNumber(); parameterSource.addValue(paramName, convertedIds, typeNumber); diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultJdbcTypeFactory.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultJdbcTypeFactory.java index c70287d1ba..09f5627f3e 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultJdbcTypeFactory.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultJdbcTypeFactory.java @@ -16,7 +16,7 @@ package org.springframework.data.jdbc.core.convert; import java.sql.Array; -import java.sql.JDBCType; +import java.sql.SQLType; import org.springframework.data.jdbc.core.dialect.JdbcArrayColumns; import org.springframework.data.jdbc.support.JdbcUtil; @@ -68,7 +68,7 @@ public Array createArray(Object[] value) { Class componentType = arrayColumns.getArrayType(value.getClass()); - JDBCType jdbcType = JdbcUtil.jdbcTypeFor(componentType); + SQLType jdbcType = JdbcUtil.targetSqlTypeFor(componentType); Assert.notNull(jdbcType, () -> String.format("Couldn't determine JDBCType for %s", componentType)); String typeName = arrayColumns.getArrayTypeName(jdbcType); diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcConverter.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcConverter.java index 31fc2e3726..6f4f1635ad 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcConverter.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcConverter.java @@ -16,6 +16,7 @@ package org.springframework.data.jdbc.core.convert; import java.sql.ResultSet; +import java.sql.SQLType; import org.springframework.data.jdbc.core.mapping.JdbcValue; import org.springframework.data.relational.core.conversion.RelationalConverter; @@ -39,12 +40,24 @@ public interface JdbcConverter extends RelationalConverter { * to JDBC parameters. * * @param value a value as it is used in the object model. May be {@code null}. - * @param type {@link TypeInformation} into which the value is to be converted. Must not be {@code null}. + * @param type {@literal Class} into which the value is to be converted. Must not be {@code null}. * @param sqlType the type constant from {@link java.sql.Types} to be used if non is specified by a converter. * @return The converted value wrapped in a {@link JdbcValue}. Guaranteed to be not {@literal null}. */ JdbcValue writeJdbcValue(@Nullable Object value, Class type, int sqlType); + /** + * Convert a property value into a {@link JdbcValue} that contains the converted value and information how to bind it + * to JDBC parameters. + * + * @param value a value as it is used in the object model. May be {@code null}. + * @param type {@literal Class} into which the value is to be converted. Must not be {@code null}. + * @param sqlType the {@link SQLType} to be used if non is specified by a converter. + * @return The converted value wrapped in a {@link JdbcValue}. Guaranteed to be not {@literal null}. + * @since 2.4 + */ + JdbcValue writeJdbcValue(@Nullable Object value, Class type, SQLType sqlType); + /** * Read the current row from {@link ResultSet} to an {@link RelationalPersistentEntity#getType() entity}. * @@ -73,7 +86,7 @@ public interface JdbcConverter extends RelationalConverter { * top-level array type (e.g. {@code String[][]} returns {@code String[]}). * * @return a {@link Class} that is suitable for usage with JDBC drivers. - * @see org.springframework.data.jdbc.support.JdbcUtil#sqlTypeFor(Class) + * @see org.springframework.data.jdbc.support.JdbcUtil#targetSqlTypeFor(Class) * @since 2.0 */ Class getColumnType(RelationalPersistentProperty property); @@ -85,5 +98,9 @@ public interface JdbcConverter extends RelationalConverter { * @see java.sql.Types * @since 2.0 */ + SQLType getTargetSqlType(RelationalPersistentProperty property); + + @Deprecated int getSqlType(RelationalPersistentProperty property); + } diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcValue.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcValue.java index c8c37b5323..e174ef44ef 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcValue.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcValue.java @@ -16,6 +16,7 @@ package org.springframework.data.jdbc.core.convert; import java.sql.JDBCType; +import java.sql.SQLType; import java.util.Objects; import org.springframework.lang.Nullable; @@ -32,11 +33,11 @@ @Deprecated public final class JdbcValue extends org.springframework.data.jdbc.core.mapping.JdbcValue { - private JdbcValue(@Nullable Object value, @Nullable JDBCType jdbcType) { + private JdbcValue(@Nullable Object value, @Nullable SQLType jdbcType) { super(value, jdbcType); } - public static JdbcValue of(@Nullable Object value, @Nullable JDBCType jdbcType) { + public static JdbcValue of(@Nullable Object value, @Nullable SQLType jdbcType) { return new JdbcValue(value, jdbcType); } } diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/mapping/JdbcValue.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/mapping/JdbcValue.java index 8e0dd48ba0..91f50417fd 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/mapping/JdbcValue.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/mapping/JdbcValue.java @@ -16,6 +16,7 @@ package org.springframework.data.jdbc.core.mapping; import java.sql.JDBCType; +import java.sql.SQLType; import java.util.Objects; import org.springframework.lang.Nullable; @@ -31,15 +32,15 @@ public class JdbcValue { private final Object value; - private final JDBCType jdbcType; + private final SQLType jdbcType; - protected JdbcValue(@Nullable Object value, @Nullable JDBCType jdbcType) { + protected JdbcValue(@Nullable Object value, @Nullable SQLType jdbcType) { this.value = value; this.jdbcType = jdbcType; } - public static JdbcValue of(@Nullable Object value, @Nullable JDBCType jdbcType) { + public static JdbcValue of(@Nullable Object value, @Nullable SQLType jdbcType) { return new JdbcValue(value, jdbcType); } @@ -49,7 +50,7 @@ public Object getValue() { } @Nullable - public JDBCType getJdbcType() { + public SQLType getJdbcType() { return this.jdbcType; } diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/QueryMapper.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/QueryMapper.java index 09b1138c21..33a3a4fad9 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/QueryMapper.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/QueryMapper.java @@ -16,7 +16,7 @@ package org.springframework.data.jdbc.repository.query; import java.sql.JDBCType; -import java.sql.Types; +import java.sql.SQLType; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -27,6 +27,7 @@ import org.springframework.data.domain.Sort; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.core.mapping.JdbcValue; +import org.springframework.data.jdbc.support.JdbcUtil; import org.springframework.data.mapping.PersistentPropertyAccessor; import org.springframework.data.mapping.PersistentPropertyPath; import org.springframework.data.mapping.PropertyPath; @@ -45,7 +46,6 @@ import org.springframework.data.util.Pair; import org.springframework.data.util.TypeInformation; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.support.JdbcUtils; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -279,7 +279,7 @@ private Condition mapCondition(CriteriaDefinition criteria, MapSqlParameterSourc TypeInformation actualType = propertyField.getTypeHint().getRequiredActualType(); Column column = table.column(propertyField.getMappedColumnName()); Object mappedValue; - int sqlType; + SQLType sqlType; if (criteria.getValue() instanceof JdbcValue) { @@ -302,7 +302,7 @@ private Condition mapCondition(CriteriaDefinition criteria, MapSqlParameterSourc RelationalPersistentProperty property = ((MetadataBackedField) propertyField).property; JdbcValue jdbcValue = convertToJdbcValue(property, criteria.getValue()); mappedValue = jdbcValue.getValue(); - sqlType = jdbcValue.getJdbcType() != null ? jdbcValue.getJdbcType().getVendorTypeNumber() + sqlType = jdbcValue.getJdbcType() != null ? jdbcValue.getJdbcType() : propertyField.getSqlType(); } else { @@ -339,7 +339,7 @@ private JdbcValue convertToJdbcValue(RelationalPersistentProperty property, @Nul if (value instanceof Iterable) { List mapped = new ArrayList<>(); - JDBCType jdbcType = null; + SQLType jdbcType = null; for (Object o : (Iterable) value) { @@ -358,7 +358,7 @@ private JdbcValue convertToJdbcValue(RelationalPersistentProperty property, @Nul Object[] valueAsArray = (Object[]) value; Object[] mappedValueArray = new Object[valueAsArray.length]; - JDBCType jdbcType = null; + SQLType jdbcType = null; for (int i = 0; i < valueAsArray.length; i++) { @@ -389,7 +389,7 @@ private JdbcValue getWriteValue(RelationalPersistentProperty property, Object va return converter.writeJdbcValue( // value, // converter.getColumnType(property), // - converter.getSqlType(property) // + converter.getTargetSqlType(property) // ); } @@ -410,7 +410,7 @@ private Condition mapEmbeddedObjectCondition(CriteriaDefinition criteria, MapSql SqlIdentifier sqlIdentifier = nestedProperty.getColumnName().transform(prefix::concat); Object mappedNestedValue = convertValue(embeddedAccessor.getProperty(nestedProperty), nestedProperty.getTypeInformation()); - int sqlType = converter.getSqlType(nestedProperty); + SQLType sqlType = converter.getTargetSqlType(nestedProperty); Condition mappedCondition = createCondition(table.column(sqlIdentifier), mappedNestedValue, sqlType, parameterSource, criteria.getComparator(), criteria.isIgnoreCase()); @@ -481,8 +481,8 @@ protected MappingContext, RelationalPers return this.mappingContext; } - private Condition createCondition(Column column, @Nullable Object mappedValue, int sqlType, - MapSqlParameterSource parameterSource, Comparator comparator, boolean ignoreCase) { + private Condition createCondition(Column column, @Nullable Object mappedValue, SQLType sqlType, + MapSqlParameterSource parameterSource, Comparator comparator, boolean ignoreCase) { if (comparator.equals(Comparator.IS_NULL)) { return column.isNull(); @@ -505,7 +505,7 @@ private Condition createCondition(Column column, @Nullable Object mappedValue, i } Expression columnExpression = column; - if (ignoreCase && (sqlType == Types.VARCHAR || sqlType == Types.NVARCHAR)) { + if (ignoreCase && (sqlType == JDBCType.VARCHAR || sqlType == JDBCType.NVARCHAR)) { columnExpression = Functions.upper(column); } @@ -593,7 +593,7 @@ private Condition createCondition(Column column, @Nullable Object mappedValue, i private Expression bindBoolean(Column column, MapSqlParameterSource parameterSource, boolean value) { Object converted = converter.writeValue(value, ClassTypeInformation.OBJECT); - return bind(converted, Types.BIT, parameterSource, column.getName().getReference()); + return bind(converted, JDBCType.BIT, parameterSource, column.getName().getReference()); } Field createPropertyField(@Nullable RelationalPersistentEntity entity, SqlIdentifier key) { @@ -605,30 +605,30 @@ Field createPropertyField(@Nullable RelationalPersistentEntity entity, SqlIde return entity == null ? new Field(key) : new MetadataBackedField(key, entity, mappingContext, converter); } - int getTypeHint(@Nullable Object mappedValue, Class propertyType, JdbcValue settableValue) { + SQLType getTypeHint(@Nullable Object mappedValue, Class propertyType, JdbcValue settableValue) { if (mappedValue == null || propertyType.equals(Object.class)) { - return JdbcUtils.TYPE_UNKNOWN; + return JdbcUtil.TYPE_UNKNOWN; } if (mappedValue.getClass().equals(settableValue.getValue().getClass())) { - return JdbcUtils.TYPE_UNKNOWN; + return JdbcUtil.TYPE_UNKNOWN; } - return settableValue.getJdbcType().getVendorTypeNumber(); + return settableValue.getJdbcType(); } - private Expression bind(@Nullable Object mappedValue, int sqlType, MapSqlParameterSource parameterSource, - String name) { + private Expression bind(@Nullable Object mappedValue, SQLType sqlType, MapSqlParameterSource parameterSource, + String name) { return bind(mappedValue, sqlType, parameterSource, name, false); } - private Expression bind(@Nullable Object mappedValue, int sqlType, MapSqlParameterSource parameterSource, String name, - boolean ignoreCase) { + private Expression bind(@Nullable Object mappedValue, SQLType sqlType, MapSqlParameterSource parameterSource, String name, + boolean ignoreCase) { String uniqueName = getUniqueName(parameterSource, name); - parameterSource.addValue(uniqueName, mappedValue, sqlType); + parameterSource.addValue(uniqueName, mappedValue, sqlType.getVendorTypeNumber()); return ignoreCase ? Functions.upper(SQL.bindMarker(":" + uniqueName)) : SQL.bindMarker(":" + uniqueName); } @@ -686,8 +686,8 @@ public TypeInformation getTypeHint() { return ClassTypeInformation.OBJECT; } - public int getSqlType() { - return JdbcUtils.TYPE_UNKNOWN; + public SQLType getSqlType() { + return JdbcUtil.TYPE_UNKNOWN; } } @@ -701,7 +701,7 @@ protected static class MetadataBackedField extends Field { private final RelationalPersistentProperty property; private final @Nullable PersistentPropertyPath path; private final boolean embedded; - private final int sqlType; + private final SQLType sqlType; /** * Creates a new {@link MetadataBackedField} with the given name, {@link RelationalPersistentEntity} and @@ -741,7 +741,7 @@ protected MetadataBackedField(SqlIdentifier name, RelationalPersistentEntity this.path = getPath(name.getReference()); this.property = this.path == null ? property : this.path.getLeafProperty(); - this.sqlType = this.property != null ? converter.getSqlType(this.property) : JdbcUtils.TYPE_UNKNOWN; + this.sqlType = this.property != null ? converter.getTargetSqlType(this.property) : JdbcUtil.TYPE_UNKNOWN; if (this.property != null) { this.embedded = this.property.isEmbedded(); @@ -839,7 +839,7 @@ public TypeInformation getTypeHint() { * @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#getSqlType() */ @Override - public int getSqlType() { + public SQLType getSqlType() { return this.sqlType; } } diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQuery.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQuery.java index e6b81296b7..2a329fb2f1 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQuery.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQuery.java @@ -18,7 +18,7 @@ import static org.springframework.data.jdbc.repository.query.JdbcQueryExecution.*; import java.lang.reflect.Constructor; -import java.sql.JDBCType; +import java.sql.SQLType; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.BeanFactory; @@ -161,9 +161,9 @@ private void convertAndAddParameter(MapSqlParameterSource parameters, Parameter Class conversionTargetType = JdbcColumnTypes.INSTANCE.resolvePrimitiveType(parameterType); JdbcValue jdbcValue = converter.writeJdbcValue(value, conversionTargetType, - JdbcUtil.sqlTypeFor(conversionTargetType)); + JdbcUtil.targetSqlTypeFor(conversionTargetType)); - JDBCType jdbcType = jdbcValue.getJdbcType(); + SQLType jdbcType = jdbcValue.getJdbcType(); if (jdbcType == null) { parameters.addValue(parameterName, jdbcValue.getValue()); diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/support/JdbcUtil.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/support/JdbcUtil.java index e5d0c291f4..29d0895876 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/support/JdbcUtil.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/support/JdbcUtil.java @@ -19,6 +19,7 @@ import java.math.BigInteger; import java.sql.Date; import java.sql.JDBCType; +import java.sql.SQLType; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; @@ -38,32 +39,48 @@ */ public final class JdbcUtil { - private static final Map, Integer> sqlTypeMappings = new HashMap<>(); + public static final SQLType TYPE_UNKNOWN = new SQLType() { + @Override + public String getName() { + return "UNKNOWN"; + } + + @Override + public String getVendor() { + return "Spring"; + } + + @Override + public Integer getVendorTypeNumber() { + return JdbcUtils.TYPE_UNKNOWN; + } + } ; + private static final Map, SQLType> sqlTypeMappings = new HashMap<>(); static { - sqlTypeMappings.put(String.class, Types.VARCHAR); - sqlTypeMappings.put(BigInteger.class, Types.BIGINT); - sqlTypeMappings.put(BigDecimal.class, Types.DECIMAL); - sqlTypeMappings.put(Byte.class, Types.TINYINT); - sqlTypeMappings.put(byte.class, Types.TINYINT); - sqlTypeMappings.put(Short.class, Types.SMALLINT); - sqlTypeMappings.put(short.class, Types.SMALLINT); - sqlTypeMappings.put(Integer.class, Types.INTEGER); - sqlTypeMappings.put(int.class, Types.INTEGER); - sqlTypeMappings.put(Long.class, Types.BIGINT); - sqlTypeMappings.put(long.class, Types.BIGINT); - sqlTypeMappings.put(Double.class, Types.DOUBLE); - sqlTypeMappings.put(double.class, Types.DOUBLE); - sqlTypeMappings.put(Float.class, Types.REAL); - sqlTypeMappings.put(float.class, Types.REAL); - sqlTypeMappings.put(Boolean.class, Types.BIT); - sqlTypeMappings.put(boolean.class, Types.BIT); - sqlTypeMappings.put(byte[].class, Types.VARBINARY); - sqlTypeMappings.put(Date.class, Types.DATE); - sqlTypeMappings.put(Time.class, Types.TIME); - sqlTypeMappings.put(Timestamp.class, Types.TIMESTAMP); - sqlTypeMappings.put(OffsetDateTime.class, Types.TIMESTAMP_WITH_TIMEZONE); + sqlTypeMappings.put(String.class, JDBCType.VARCHAR); + sqlTypeMappings.put(BigInteger.class, JDBCType.BIGINT); + sqlTypeMappings.put(BigDecimal.class, JDBCType.DECIMAL); + sqlTypeMappings.put(Byte.class, JDBCType.TINYINT); + sqlTypeMappings.put(byte.class, JDBCType.TINYINT); + sqlTypeMappings.put(Short.class, JDBCType.SMALLINT); + sqlTypeMappings.put(short.class, JDBCType.SMALLINT); + sqlTypeMappings.put(Integer.class, JDBCType.INTEGER); + sqlTypeMappings.put(int.class, JDBCType.INTEGER); + sqlTypeMappings.put(Long.class, JDBCType.BIGINT); + sqlTypeMappings.put(long.class, JDBCType.BIGINT); + sqlTypeMappings.put(Double.class, JDBCType.DOUBLE); + sqlTypeMappings.put(double.class, JDBCType.DOUBLE); + sqlTypeMappings.put(Float.class, JDBCType.REAL); + sqlTypeMappings.put(float.class, JDBCType.REAL); + sqlTypeMappings.put(Boolean.class, JDBCType.BIT); + sqlTypeMappings.put(boolean.class, JDBCType.BIT); + sqlTypeMappings.put(byte[].class, JDBCType.VARBINARY); + sqlTypeMappings.put(Date.class, JDBCType.DATE); + sqlTypeMappings.put(Time.class, JDBCType.TIME); + sqlTypeMappings.put(Timestamp.class, JDBCType.TIMESTAMP); + sqlTypeMappings.put(OffsetDateTime.class, JDBCType.TIMESTAMP_WITH_TIMEZONE); } private JdbcUtil() { @@ -76,7 +93,9 @@ private JdbcUtil() { * * @param type The type of value to be bound to a {@link java.sql.PreparedStatement}. * @return One of the values defined in {@link Types} or {@link JdbcUtils#TYPE_UNKNOWN}. + * @deprecated use {@link #targetSqlTypeFor(Class)} instead. */ + @Deprecated public static int sqlTypeFor(Class type) { Assert.notNull(type, "Type must not be null."); @@ -85,16 +104,36 @@ public static int sqlTypeFor(Class type) { .filter(k -> k.isAssignableFrom(type)) // .findFirst() // .map(sqlTypeMappings::get) // + .map(SQLType::getVendorTypeNumber) .orElse(JdbcUtils.TYPE_UNKNOWN); } + /** + * Returns the {@link SQLType} value suitable for passing a value of the provided type to JDBC driver. + * + * @param type The type of value to be bound to a {@link java.sql.PreparedStatement}. + * @return a matching {@link SQLType} or {@link #TYPE_UNKNOWN}. + */ + public static SQLType targetSqlTypeFor(Class type) { + + Assert.notNull(type, "Type must not be null."); + + return sqlTypeMappings.keySet().stream() // + .filter(k -> k.isAssignableFrom(type)) // + .findFirst() // + .map(sqlTypeMappings::get) // + .orElse(JdbcUtil.TYPE_UNKNOWN); + } + /** * Converts a {@link JDBCType} to an {@code int} value as defined in {@link Types}. * * @param jdbcType value to be converted. May be {@literal null}. * @return One of the values defined in {@link Types} or {@link JdbcUtils#TYPE_UNKNOWN}. + * @deprecated there is no replacement. */ - public static int sqlTypeFor(@Nullable JDBCType jdbcType) { + @Deprecated + public static int sqlTypeFor(@Nullable SQLType jdbcType) { return jdbcType == null ? JdbcUtils.TYPE_UNKNOWN : jdbcType.getVendorTypeNumber(); } @@ -104,9 +143,11 @@ public static int sqlTypeFor(@Nullable JDBCType jdbcType) { * * @param sqlType One of the values defined in {@link Types} or {@link JdbcUtils#TYPE_UNKNOWN}. * @return a matching {@link JDBCType} instance or {@literal null}. + * @deprecated This is now a noop */ @Nullable - public static JDBCType jdbcTypeFor(int sqlType) { + @Deprecated + public static SQLType jdbcTypeFor(int sqlType) { if (sqlType == JdbcUtils.TYPE_UNKNOWN) { return null; @@ -121,9 +162,11 @@ public static JDBCType jdbcTypeFor(int sqlType) { * * @param type The type of value to be bound to a {@link java.sql.PreparedStatement}. * @return a matching {@link JDBCType} instance or {@literal null}. + * @deprecated Use {@link #targetSqlTypeFor(Class)} instead. */ - @Nullable - public static JDBCType jdbcTypeFor(Class type) { - return jdbcTypeFor(sqlTypeFor(type)); + @Deprecated + public static SQLType jdbcTypeFor(Class type) { + + return targetSqlTypeFor(type); } } diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverterUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverterUnitTests.java index e382206680..70b7763c92 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverterUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverterUnitTests.java @@ -136,7 +136,7 @@ void conversionOfDateLikeValueAndBackYieldsOriginalValue() { void conversionOfPrimitiveArrays() { int[] ints = { 1, 2, 3, 4, 5 }; - JdbcValue converted = converter.writeJdbcValue(ints, ints.getClass(), JdbcUtil.sqlTypeFor(ints.getClass())); + JdbcValue converted = converter.writeJdbcValue(ints, ints.getClass(), JdbcUtil.targetSqlTypeFor(ints.getClass())); assertThat(converted.getValue()).isInstanceOf(Array.class); assertThat(typeFactory.arraySource).containsExactly(1, 2, 3, 4, 5); diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/support/JdbcUtilTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/support/JdbcUtilTests.java index 371c752289..eb52f0f12d 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/support/JdbcUtilTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/support/JdbcUtilTests.java @@ -17,7 +17,7 @@ import static org.assertj.core.api.Assertions.*; -import java.sql.Types; +import java.sql.JDBCType; import java.time.OffsetDateTime; import org.junit.jupiter.api.Test; @@ -31,6 +31,6 @@ class JdbcUtilTests { @Test void test() { - assertThat(JdbcUtil.sqlTypeFor(OffsetDateTime.class)).isEqualTo(Types.TIMESTAMP_WITH_TIMEZONE); + assertThat(JdbcUtil.targetSqlTypeFor(OffsetDateTime.class)).isEqualTo(JDBCType.TIMESTAMP_WITH_TIMEZONE); } } diff --git a/spring-data-relational/pom.xml b/spring-data-relational/pom.xml index a6eb48c891..1b84f56271 100644 --- a/spring-data-relational/pom.xml +++ b/spring-data-relational/pom.xml @@ -6,7 +6,7 @@ 4.0.0 spring-data-relational - 2.4.0-SNAPSHOT + 2.4.0-1089-sql-type-SNAPSHOT Spring Data Relational Spring Data Relational support @@ -14,7 +14,7 @@ org.springframework.data spring-data-relational-parent - 2.4.0-SNAPSHOT + 2.4.0-1089-sql-type-SNAPSHOT