From c263366641c018af76cbb753830107db1fccf0d6 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Sat, 22 Feb 2025 13:06:19 -0500 Subject: [PATCH] Fix Nullability Error A type converter could return null. This was not properly handled by the ValueWhenPresentMapping. --- .../sql/util/ValueWhenPresentMapping.java | 6 ++-- .../spring/LastNameParameterConverter.java | 9 ++++-- .../examples/spring/PersonTemplateTest.java | 28 +++++++++++++++++++ .../examples/simple/CreateSimpleDB.sql | 2 +- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/mybatis/dynamic/sql/util/ValueWhenPresentMapping.java b/src/main/java/org/mybatis/dynamic/sql/util/ValueWhenPresentMapping.java index a9dae6c66..5420c644e 100644 --- a/src/main/java/org/mybatis/dynamic/sql/util/ValueWhenPresentMapping.java +++ b/src/main/java/org/mybatis/dynamic/sql/util/ValueWhenPresentMapping.java @@ -35,11 +35,11 @@ private ValueWhenPresentMapping(SqlColumn column, Supplier<@Nullable T> value } public Optional value() { - return Optional.ofNullable(valueSupplier.get()).map(this::convert); + return Optional.ofNullable(valueSupplier.get()).flatMap(this::convert); } - private @Nullable Object convert(@Nullable T value) { - return localColumn.convertParameterType(value); + private Optional convert(T value) { + return Optional.ofNullable(localColumn.convertParameterType(value)); } @Override diff --git a/src/test/java/examples/spring/LastNameParameterConverter.java b/src/test/java/examples/spring/LastNameParameterConverter.java index 2a45753d7..e8d57d4cd 100644 --- a/src/test/java/examples/spring/LastNameParameterConverter.java +++ b/src/test/java/examples/spring/LastNameParameterConverter.java @@ -16,6 +16,7 @@ package examples.spring; import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; import org.mybatis.dynamic.sql.ParameterTypeConverter; import org.springframework.core.convert.converter.Converter; @@ -23,7 +24,11 @@ public class LastNameParameterConverter implements ParameterTypeConverter, Converter { @Override - public String convert(LastName source) { - return source.getName(); + public @Nullable String convert(LastName source) { + if ("Slate".equals(source.getName())) { + return null; + } else { + return source.getName(); + } } } diff --git a/src/test/java/examples/spring/PersonTemplateTest.java b/src/test/java/examples/spring/PersonTemplateTest.java index 3934d3125..8376dcef7 100644 --- a/src/test/java/examples/spring/PersonTemplateTest.java +++ b/src/test/java/examples/spring/PersonTemplateTest.java @@ -31,6 +31,8 @@ import org.mybatis.dynamic.sql.insert.GeneralInsertModel; import org.mybatis.dynamic.sql.insert.InsertModel; import org.mybatis.dynamic.sql.insert.MultiRowInsertModel; +import org.mybatis.dynamic.sql.insert.render.GeneralInsertStatementProvider; +import org.mybatis.dynamic.sql.render.RenderingStrategies; import org.mybatis.dynamic.sql.select.SelectModel; import org.mybatis.dynamic.sql.update.UpdateModel; import org.mybatis.dynamic.sql.util.Buildable; @@ -379,6 +381,32 @@ void testInsertSelective() { assertThat(rows).isEqualTo(1); } + @Test + void testGeneralInsertWhenTypeConverterReturnsNull() { + + GeneralInsertStatementProvider insertStatement = insertInto(person) + .set(id).toValue(100) + .set(firstName).toValue("Joe") + .set(lastName).toValueWhenPresent(LastName.of("Slate")) + .set(birthDate).toValue(new Date()) + .set(employed).toValue(true) + .set(occupation).toValue("Quarry Owner") + .set(addressId).toValue(1) + .build() + .render(RenderingStrategies.SPRING_NAMED_PARAMETER); + + assertThat(insertStatement.getInsertStatement()) + .isEqualTo("insert into Person (id, first_name, birth_date, employed, occupation, address_id) values (:p1, :p2, :p3, :p4, :p5, :p6)"); + int rows = template.generalInsert(insertStatement); + assertThat(rows).isEqualTo(1); + + Buildable selectStatement = select(id, firstName, lastName, birthDate, employed, occupation, addressId) + .from(person) + .where(id, isEqualTo(100)); + Optional newRecord = template.selectOne(selectStatement, personRowMapper); + assertThat(newRecord).hasValueSatisfying(r -> assertThat(r.getLastName().getName()).isNull()); + } + @Test void testUpdateByPrimaryKey() { diff --git a/src/test/resources/examples/simple/CreateSimpleDB.sql b/src/test/resources/examples/simple/CreateSimpleDB.sql index a60c51ef9..c335c4215 100644 --- a/src/test/resources/examples/simple/CreateSimpleDB.sql +++ b/src/test/resources/examples/simple/CreateSimpleDB.sql @@ -30,7 +30,7 @@ create table Address ( create table Person ( id int not null, first_name varchar(30) not null, - last_name varchar(30) not null, + last_name varchar(30) null, birth_date date not null, employed varchar(3) not null, occupation varchar(30) null,