Skip to content

Commit 90b0f45

Browse files
authored
Add a couple missing java.time types to StatementCreatorUtils
This commit adds mapping for two types from the `java.time` package, complementing the types that are already translatable to Sql types TIME, DATE and TIMESTAMP: - `OffsetTime` maps to a `TIME_WITH_TIMEZONE` - `OffsetDateTime` maps to a `TIMESTAMP_WITH_TIMEZONE` This is in accordance with the B.4 table provided in the JDBC 4.2 specification. When preparing statements, these `java.time` types use the `setObject` method. Tests covering the 5 `java.time` classes have also been added. See gh-28778 See gh-28527 Closes gh-30123
1 parent 9fb61c5 commit 90b0f45

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

spring-jdbc/src/main/java/org/springframework/jdbc/core/StatementCreatorUtils.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import java.time.LocalDate;
3030
import java.time.LocalDateTime;
3131
import java.time.LocalTime;
32+
import java.time.OffsetDateTime;
33+
import java.time.OffsetTime;
3234
import java.util.Arrays;
3335
import java.util.Calendar;
3436
import java.util.Collection;
@@ -104,6 +106,8 @@ public abstract class StatementCreatorUtils {
104106
javaTypeToSqlTypeMap.put(LocalDate.class, Types.DATE);
105107
javaTypeToSqlTypeMap.put(LocalTime.class, Types.TIME);
106108
javaTypeToSqlTypeMap.put(LocalDateTime.class, Types.TIMESTAMP);
109+
javaTypeToSqlTypeMap.put(OffsetDateTime.class, Types.TIMESTAMP_WITH_TIMEZONE);
110+
javaTypeToSqlTypeMap.put(OffsetTime.class, Types.TIME_WITH_TIMEZONE);
107111
javaTypeToSqlTypeMap.put(java.sql.Date.class, Types.DATE);
108112
javaTypeToSqlTypeMap.put(java.sql.Time.class, Types.TIME);
109113
javaTypeToSqlTypeMap.put(java.sql.Timestamp.class, Types.TIMESTAMP);

spring-jdbc/src/test/java/org/springframework/jdbc/core/StatementCreatorUtilsTests.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,20 @@
2222
import java.sql.PreparedStatement;
2323
import java.sql.SQLException;
2424
import java.sql.Types;
25+
import java.time.LocalDate;
26+
import java.time.LocalDateTime;
27+
import java.time.LocalTime;
28+
import java.time.ZoneOffset;
2529
import java.util.GregorianCalendar;
30+
import java.util.stream.Stream;
2631

2732
import org.junit.jupiter.api.Test;
33+
import org.junit.jupiter.params.ParameterizedTest;
34+
import org.junit.jupiter.params.provider.Arguments;
35+
import org.junit.jupiter.params.provider.MethodSource;
2836

37+
import static org.assertj.core.api.Assertions.assertThat;
38+
import static org.junit.jupiter.api.Named.named;
2939
import static org.mockito.BDDMockito.given;
3040
import static org.mockito.Mockito.mock;
3141
import static org.mockito.Mockito.never;
@@ -203,6 +213,35 @@ public void testSetParameterValueWithCalendarAndUnknownType() throws SQLExceptio
203213
verify(preparedStatement).setTimestamp(1, new java.sql.Timestamp(cal.getTime().getTime()), cal);
204214
}
205215

216+
217+
@ParameterizedTest
218+
@MethodSource("javaTimeTypes")
219+
public void testSetParameterValueWithJavaTimeTypes(Object o, int sqlType) throws SQLException {
220+
StatementCreatorUtils.setParameterValue(preparedStatement, 1, sqlType, null, o);
221+
verify(preparedStatement).setObject(1, o, sqlType);
222+
}
223+
224+
@ParameterizedTest
225+
@MethodSource("javaTimeTypes")
226+
void javaTimeTypesToSqlParameterType(Object o, int expectedSqlType) {
227+
assertThat(StatementCreatorUtils.javaTypeToSqlParameterType(o.getClass()))
228+
.isEqualTo(expectedSqlType);
229+
}
230+
231+
static Stream<Arguments> javaTimeTypes() {
232+
ZoneOffset PLUS_NINE = ZoneOffset.ofHours(9);
233+
final LocalDateTime now = LocalDateTime.now();
234+
return Stream.of(
235+
Arguments.of(named("LocalTime", LocalTime.NOON), named("TIME", Types.TIME)),
236+
Arguments.of(named("LocalDate", LocalDate.EPOCH), named("DATE", Types.DATE)),
237+
Arguments.of(named("LocalDateTime", now), named("TIMESTAMP", Types.TIMESTAMP)),
238+
Arguments.of(named("OffsetTime", LocalTime.NOON.atOffset(PLUS_NINE)),
239+
named("TIME_WITH_TIMEZONE", Types.TIME_WITH_TIMEZONE)),
240+
Arguments.of(named("OffsetDateTime", now.atOffset(PLUS_NINE)),
241+
named("TIMESTAMP_WITH_TIMEZONE", Types.TIMESTAMP_WITH_TIMEZONE))
242+
);
243+
}
244+
206245
@Test // SPR-8571
207246
public void testSetParameterValueWithStringAndVendorSpecificType() throws SQLException {
208247
Connection con = mock();

0 commit comments

Comments
 (0)