From 290800b1dec3cf69f61138d56471f0bc642dd52f Mon Sep 17 00:00:00 2001 From: Sergey Korotaev Date: Tue, 3 Jun 2025 22:20:34 +0300 Subject: [PATCH] Add default JDBCType.NULL for null values Signed-off-by: Sergey Korotaev --- .../core/convert/SqlParametersFactory.java | 10 +- .../convert/SqlParametersFactoryTest.java | 92 +++++++++++++++++++ 2 files changed, 97 insertions(+), 5 deletions(-) diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlParametersFactory.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlParametersFactory.java index 8bf9bb869f..1905bc196d 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlParametersFactory.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlParametersFactory.java @@ -15,6 +15,7 @@ */ package org.springframework.data.jdbc.core.convert; +import java.sql.JDBCType; import java.sql.SQLType; import java.util.ArrayList; import java.util.List; @@ -41,6 +42,7 @@ * @author Jens Schauder * @author Chirag Tailor * @author Mikhail Polivakha + * @author Sergey Korotaev * @since 2.4 */ public class SqlParametersFactory { @@ -187,11 +189,9 @@ private void addConvertedPropertyValue(SqlIdentifierParameterSource parameterSou private void addConvertedValue(SqlIdentifierParameterSource parameterSource, @Nullable Object value, SqlIdentifier paramName, Class javaType, SQLType sqlType) { - JdbcValue jdbcValue = converter.writeJdbcValue( // - value, // - javaType, // - sqlType // - ); + JdbcValue jdbcValue = value != null + ? converter.writeJdbcValue(value, javaType, sqlType) + : JdbcValue.of(null, JDBCType.NULL); parameterSource.addValue( // paramName, // diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlParametersFactoryTest.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlParametersFactoryTest.java index 9efdb3aeab..2d5e5ee6df 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlParametersFactoryTest.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlParametersFactoryTest.java @@ -21,6 +21,7 @@ import static org.mockito.Mockito.*; import static org.springframework.data.jdbc.core.convert.DefaultDataAccessStrategyUnitTests.*; +import java.sql.JDBCType; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -32,6 +33,7 @@ import org.springframework.data.convert.ReadingConverter; import org.springframework.data.convert.WritingConverter; import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; +import org.springframework.data.jdbc.core.mapping.JdbcValue; import org.springframework.data.relational.core.conversion.IdValueSource; import org.springframework.data.relational.core.mapping.Column; import org.springframework.data.relational.core.mapping.RelationalMappingContext; @@ -42,6 +44,7 @@ * Unit tests for {@link SqlParametersFactory}. * * @author Chirag Tailor + * @author Sergey Korotaev */ class SqlParametersFactoryTest { @@ -162,6 +165,69 @@ void parameterNamesGetSanitized() { assertThat(sqlParameterSource.getValue("val&ue")).isNull(); } + @Test + // GH-1935 + void enumParameterIsNotNullReturnCorrectSqlTypeFromConverter() { + + WithEnumEntity entity = new WithEnumEntity(23L, DummyEnum.ONE); + + SqlParametersFactory sqlParametersFactory = createSqlParametersFactoryWithConverters( + singletonList(WritingEnumConverter.INSTANCE)); + + SqlIdentifierParameterSource sqlParameterSource = sqlParametersFactory.forInsert(entity, + WithEnumEntity.class, Identifier.empty(), IdValueSource.PROVIDED); + + assertThat(sqlParameterSource.getValue("id")).isEqualTo(23L); + assertThat(sqlParameterSource.getValue("dummy_enum")).isEqualTo(DummyEnum.ONE.name()); + assertThat(sqlParameterSource.getSqlType("dummy_enum")).isEqualTo(1111); + } + + @Test + // GH-1935 + void enumParameterIsNullReturnCorrectSqlTypeFromConverter() { + WithEnumEntity entity = new WithEnumEntity(23L, null); + + SqlParametersFactory sqlParametersFactory = createSqlParametersFactoryWithConverters( + singletonList(WritingEnumConverter.INSTANCE)); + + SqlIdentifierParameterSource sqlParameterSource = sqlParametersFactory.forInsert(entity, + WithEnumEntity.class, Identifier.empty(), IdValueSource.PROVIDED); + + assertThat(sqlParameterSource.getValue("id")).isEqualTo(23L); + assertThat(sqlParameterSource.getSqlType("dummy_enum")).isEqualTo(JDBCType.NULL.getVendorTypeNumber()); + assertThat(sqlParameterSource.getValue("dummy_enum")).isNull(); + } + + @Test + // GH-1935 + void enumParameterIsNotNullReturnCorrectSqlTypeWithoutConverter() { + + WithEnumEntity entity = new WithEnumEntity(23L, DummyEnum.ONE); + + SqlIdentifierParameterSource sqlParameterSource = sqlParametersFactory.forInsert(entity, + WithEnumEntity.class, Identifier.empty(), IdValueSource.PROVIDED); + + assertThat(sqlParameterSource.getValue("id")).isEqualTo(23L); + assertThat(sqlParameterSource.getValue("dummy_enum")).isEqualTo(DummyEnum.ONE.name()); + assertThat(sqlParameterSource.getSqlType("dummy_enum")).isEqualTo(12); + + } + + @Test + // GH-1935 + void enumParameterIsNullReturnCorrectSqlTypeWithoutConverter() { + + WithEnumEntity entity = new WithEnumEntity(23L, null); + + SqlIdentifierParameterSource sqlParameterSource = sqlParametersFactory.forInsert(entity, + WithEnumEntity.class, Identifier.empty(), IdValueSource.PROVIDED); + + assertThat(sqlParameterSource.getValue("id")).isEqualTo(23L); + assertThat(sqlParameterSource.getSqlType("dummy_enum")).isEqualTo(JDBCType.NULL.getVendorTypeNumber()); + assertThat(sqlParameterSource.getValue("dummy_enum")).isNull(); + + } + @WritingConverter enum IdValueToStringConverter implements Converter { @@ -229,6 +295,17 @@ public String toString() { } } + @WritingConverter + enum WritingEnumConverter implements Converter { + + INSTANCE; + + @Override + public JdbcValue convert(DummyEnum source) { + return JdbcValue.of(source.name().toUpperCase(), JDBCType.OTHER); + } + } + @WritingConverter enum BooleanToStringConverter implements Converter { @@ -295,6 +372,21 @@ public WithIllegalCharacters(Long id, String value) { } } + private static class WithEnumEntity { + @Id Long id; + + DummyEnum dummyEnum; + + public WithEnumEntity(Long id, DummyEnum dummyEnum) { + this.id = id; + this.dummyEnum = dummyEnum; + } + } + + private enum DummyEnum { + ONE, TWO + } + private SqlParametersFactory createSqlParametersFactoryWithConverters(List converters) { MappingJdbcConverter converter = new MappingJdbcConverter(context, relationResolver,