diff --git a/pom.xml b/pom.xml index eeaa0b9e93..75c41a315d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-relational-parent - 2.3.0-SNAPSHOT + 2.3.0-974-no-conversion-to-timestamp-for-postgres-SNAPSHOT pom Spring Data Relational Parent diff --git a/spring-data-jdbc-distribution/pom.xml b/spring-data-jdbc-distribution/pom.xml index 03d6a5c2a0..22d2b54a3d 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.3.0-SNAPSHOT + 2.3.0-974-no-conversion-to-timestamp-for-postgres-SNAPSHOT ../pom.xml diff --git a/spring-data-jdbc/pom.xml b/spring-data-jdbc/pom.xml index af9ad0904e..c8946e60cf 100644 --- a/spring-data-jdbc/pom.xml +++ b/spring-data-jdbc/pom.xml @@ -6,7 +6,7 @@ 4.0.0 spring-data-jdbc - 2.3.0-SNAPSHOT + 2.3.0-974-no-conversion-to-timestamp-for-postgres-SNAPSHOT Spring Data JDBC Spring Data module for JDBC repositories. @@ -15,7 +15,7 @@ org.springframework.data spring-data-relational-parent - 2.3.0-SNAPSHOT + 2.3.0-974-no-conversion-to-timestamp-for-postgres-SNAPSHOT diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcColumnTypes.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcColumnTypes.java index bb7a0ef3d1..a5f2cc9136 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcColumnTypes.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcColumnTypes.java @@ -16,6 +16,7 @@ package org.springframework.data.jdbc.core.convert; import java.sql.Timestamp; +import java.time.LocalDateTime; import java.time.OffsetDateTime; import java.time.ZonedDateTime; import java.time.temporal.Temporal; @@ -54,6 +55,7 @@ public Class resolvePrimitiveType(Class type) { javaToDbType.put(Enum.class, String.class); javaToDbType.put(ZonedDateTime.class, String.class); javaToDbType.put(OffsetDateTime.class, OffsetDateTime.class); + javaToDbType.put(LocalDateTime.class, LocalDateTime.class); javaToDbType.put(Temporal.class, Timestamp.class); } diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcCustomConversions.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcCustomConversions.java index 97a5b3cbc7..e91329b8b6 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcCustomConversions.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcCustomConversions.java @@ -15,11 +15,9 @@ */ package org.springframework.data.jdbc.core.convert; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.function.Predicate; import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair; import org.springframework.data.convert.CustomConversions; @@ -38,7 +36,8 @@ */ public class JdbcCustomConversions extends CustomConversions { - private static final Collection STORE_CONVERTERS = Collections.unmodifiableCollection(Jsr310TimestampBasedConverters.getConvertersToRegister()); + private static final Collection STORE_CONVERTERS = Collections + .unmodifiableCollection(Jsr310TimestampBasedConverters.getConvertersToRegister()); private static final StoreConversions STORE_CONVERSIONS = StoreConversions.of(JdbcSimpleTypes.HOLDER, STORE_CONVERTERS); @@ -50,21 +49,33 @@ public JdbcCustomConversions() { } /** - * Create a new {@link JdbcCustomConversions} instance registering the given converters and the default store converters. + * Create a new {@link JdbcCustomConversions} instance registering the given converters and the default store + * converters. * * @param converters must not be {@literal null}. */ public JdbcCustomConversions(List converters) { - super(new ConverterConfiguration(STORE_CONVERSIONS, converters, JdbcCustomConversions::isDateTimeApiConversion)); + + super(new ConverterConfiguration( // + STORE_CONVERSIONS, // + converters, // + JdbcCustomConversions::excludeConversionsBetweenDateAndJsr310Types // + )); } /** - * Create a new {@link JdbcCustomConversions} instance registering the given converters and the default store converters. + * Create a new {@link JdbcCustomConversions} instance registering the given converters and the default store + * converters. * * @since 2.3 */ public JdbcCustomConversions(StoreConversions storeConversions, List userConverters) { - super(new ConverterConfiguration(storeConversions, userConverters, JdbcCustomConversions::isDateTimeApiConversion)); + + super(new ConverterConfiguration( // + storeConversions, // + userConverters, // + JdbcCustomConversions::excludeConversionsBetweenDateAndJsr310Types // + )); } /** @@ -98,6 +109,10 @@ private static boolean isDateTimeApiConversion(ConvertiblePair cp) { return cp.getSourceType().getTypeName().startsWith("java.time."); } - return true; + return false; + } + + private static boolean excludeConversionsBetweenDateAndJsr310Types(ConvertiblePair cp) { + return !isDateTimeApiConversion(cp); } } diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/Jsr310TimestampBasedConverters.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/Jsr310TimestampBasedConverters.java index a509ad128f..a331c8183d 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/Jsr310TimestampBasedConverters.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/Jsr310TimestampBasedConverters.java @@ -45,22 +45,21 @@ * @author Jens Schauder * @since 2.2 */ -abstract class Jsr310TimestampBasedConverters { - - private static final List> CLASSES = Arrays.asList(LocalDateTime.class, LocalDate.class, LocalTime.class, - Instant.class, ZoneId.class, Duration.class, Period.class); +public abstract class Jsr310TimestampBasedConverters { /** - * Returns the converters to be registered. Will only return converters in case we're running on Java 8. + * Returns the converters to be registered. + * + * Note that the {@link LocalDateTimeToTimestampConverter} is not included, since many database don't need that conversion. + * Databases that do need it, should include it in the conversions offered by their respective dialect. * - * @return + * @return a collection of converters. Guaranteed to be not {@literal null}. */ public static Collection> getConvertersToRegister() { List> converters = new ArrayList<>(8); converters.add(TimestampToLocalDateTimeConverter.INSTANCE); - converters.add(LocalDateTimeToTimestampConverter.INSTANCE); converters.add(TimestampToLocalDateConverter.INSTANCE); converters.add(LocalDateToTimestampConverter.INSTANCE); converters.add(TimestampToLocalTimeConverter.INSTANCE); diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/dialect/JdbcDb2Dialect.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/dialect/JdbcDb2Dialect.java index d99f9cc39a..45a8c58eca 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/dialect/JdbcDb2Dialect.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/dialect/JdbcDb2Dialect.java @@ -23,6 +23,7 @@ import org.springframework.core.convert.converter.Converter; import org.springframework.data.convert.WritingConverter; +import org.springframework.data.jdbc.core.convert.Jsr310TimestampBasedConverters; import org.springframework.data.relational.core.dialect.Db2Dialect; /** @@ -43,6 +44,7 @@ public Collection getConverters() { List converters = new ArrayList<>(super.getConverters()); converters.add(OffsetDateTimeToTimestampConverter.INSTANCE); + converters.add(Jsr310TimestampBasedConverters.LocalDateTimeToTimestampConverter.INSTANCE); return converters; } diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/dialect/JdbcMySqlDialect.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/dialect/JdbcMySqlDialect.java index 2dd8a86907..07491ce60f 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/dialect/JdbcMySqlDialect.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/dialect/JdbcMySqlDialect.java @@ -15,17 +15,23 @@ */ package org.springframework.data.jdbc.core.dialect; +import static java.time.ZoneId.*; + import java.sql.JDBCType; +import java.time.LocalDateTime; import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Collection; +import java.util.Date; import org.springframework.core.convert.converter.Converter; +import org.springframework.data.convert.ReadingConverter; import org.springframework.data.convert.WritingConverter; import org.springframework.data.jdbc.core.convert.JdbcValue; import org.springframework.data.relational.core.dialect.Db2Dialect; import org.springframework.data.relational.core.dialect.MySqlDialect; import org.springframework.data.relational.core.sql.IdentifierProcessing; +import org.springframework.lang.NonNull; /** * {@link Db2Dialect} that registers JDBC specific converters. @@ -47,6 +53,7 @@ public Collection getConverters() { ArrayList converters = new ArrayList<>(super.getConverters()); converters.add(OffsetDateTimeToTimestampJdbcValueConverter.INSTANCE); + converters.add(LocalDateTimeToDateConverter.INSTANCE); return converters; } @@ -61,4 +68,16 @@ public JdbcValue convert(OffsetDateTime source) { return JdbcValue.of(source, JDBCType.TIMESTAMP); } } + + @ReadingConverter + enum LocalDateTimeToDateConverter implements Converter { + + INSTANCE; + + @NonNull + @Override + public Date convert(LocalDateTime source) { + return Date.from(source.atZone(systemDefault()).toInstant()); + } + } } diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AggregateChangeIdGenerationUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AggregateChangeIdGenerationUnitTests.java index 76555053af..1d7086e3e3 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AggregateChangeIdGenerationUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AggregateChangeIdGenerationUnitTests.java @@ -17,6 +17,7 @@ import static java.util.Collections.*; import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.SoftAssertions.*; import static org.mockito.Mockito.*; import java.util.ArrayList; @@ -26,7 +27,6 @@ import java.util.Map; import java.util.Set; -import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -87,7 +87,7 @@ public void simpleReference() { executor.execute(aggregateChange); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(entity.rootId).isEqualTo(1); softly.assertThat(entity.single.id).isEqualTo(2); @@ -107,7 +107,7 @@ public void listReference() { executor.execute(aggregateChange); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(entity.rootId).isEqualTo(1); softly.assertThat(entity.contentList).extracting(c -> c.id).containsExactly(2, 3); @@ -171,7 +171,7 @@ public void setIdForDeepReferenceElementList() { executor.execute(aggregateChange); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(entity.rootId).isEqualTo(1); softly.assertThat(entity.single.id).isEqualTo(2); @@ -198,7 +198,7 @@ public void setIdForDeepElementSetElementSet() { executor.execute(aggregateChange); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(entity.rootId).isEqualTo(1); softly.assertThat(entity.contentSet) // @@ -233,7 +233,7 @@ public void setIdForDeepElementListSingleReference() { executor.execute(aggregateChange); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(entity.rootId).isEqualTo(1); softly.assertThat(entity.contentList) // @@ -267,7 +267,7 @@ public void setIdForDeepElementListElementList() { executor.execute(aggregateChange); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(entity.rootId).isEqualTo(1); softly.assertThat(entity.contentList) // @@ -305,7 +305,7 @@ public void setIdForDeepElementMapElementMap() { executor.execute(aggregateChange); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(entity.rootId).isEqualTo(1); softly.assertThat(entity.contentMap.entrySet()) // diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java index 835ec9db5d..371c47b923 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java @@ -17,6 +17,7 @@ import static java.util.Collections.*; import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.SoftAssertions.*; import static org.springframework.data.jdbc.testing.TestDatabaseFeatures.Feature.*; import static org.springframework.test.context.TestExecutionListeners.MergeMode.*; @@ -664,7 +665,7 @@ public void shouldDeleteChainOfListsWithoutIds() { NoIdListChain4 saved = template.save(createNoIdTree()); template.deleteById(saved.four, NoIdListChain4.class); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(count("NO_ID_LIST_CHAIN4")).describedAs("Chain4 elements got deleted").isEqualTo(0); softly.assertThat(count("NO_ID_LIST_CHAIN3")).describedAs("Chain3 elements got deleted").isEqualTo(0); @@ -691,7 +692,7 @@ public void shouldDeleteChainOfMapsWithoutIds() { NoIdMapChain4 saved = template.save(createNoIdMapTree()); template.deleteById(saved.four, NoIdMapChain4.class); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(count("NO_ID_MAP_CHAIN4")).describedAs("Chain4 elements got deleted").isEqualTo(0); softly.assertThat(count("NO_ID_MAP_CHAIN3")).describedAs("Chain3 elements got deleted").isEqualTo(0); 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 1eed43cfa8..7f21e24bf1 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 @@ -16,6 +16,7 @@ package org.springframework.data.jdbc.core.convert; import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.SoftAssertions.*; import static org.mockito.Mockito.*; import lombok.Data; @@ -26,6 +27,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; +import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.util.Date; @@ -69,12 +71,14 @@ public void testTargetTypesForPropertyType() { SoftAssertions softly = new SoftAssertions(); checkTargetType(softly, entity, "someEnum", String.class); - checkTargetType(softly, entity, "localDateTime", Timestamp.class); + checkTargetType(softly, entity, "localDateTime", LocalDateTime.class); checkTargetType(softly, entity, "localDate", Timestamp.class); checkTargetType(softly, entity, "localTime", Timestamp.class); + checkTargetType(softly, entity, "zonedDateTime", String.class); + checkTargetType(softly, entity, "offsetDateTime", OffsetDateTime.class); checkTargetType(softly, entity, "instant", Timestamp.class); checkTargetType(softly, entity, "date", Date.class); - checkTargetType(softly, entity, "zonedDateTime", String.class); + checkTargetType(softly, entity, "timestamp", Timestamp.class); checkTargetType(softly, entity, "uuid", UUID.class); softly.assertAll(); @@ -116,7 +120,7 @@ void conversionOfDateLikeValueAndBackYieldsOriginalValue() { RelationalPersistentEntity persistentEntity = context.getRequiredPersistentEntity(DummyEntity.class); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { LocalDateTime testLocalDateTime = LocalDateTime.of(2001, 2, 3, 4, 5, 6, 123456789); checkConversionToTimestampAndBack(softly, persistentEntity, "localDateTime", testLocalDateTime); checkConversionToTimestampAndBack(softly, persistentEntity, "localDate", LocalDate.of(2001, 2, 3)); @@ -165,9 +169,11 @@ private static class DummyEntity { private final LocalDateTime localDateTime; private final LocalDate localDate; private final LocalTime localTime; + private final ZonedDateTime zonedDateTime; + private final OffsetDateTime offsetDateTime; private final Instant instant; private final Date date; - private final ZonedDateTime zonedDateTime; + private final Timestamp timestamp; private final AggregateReference reference; private final UUID uuid; diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/EntityRowMapperUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/EntityRowMapperUnitTests.java index 94a01985af..a4cd975c4b 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/EntityRowMapperUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/EntityRowMapperUnitTests.java @@ -18,6 +18,7 @@ import static java.util.Arrays.*; import static java.util.Collections.*; import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.SoftAssertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; @@ -43,12 +44,10 @@ import javax.naming.OperationNotSupportedException; -import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; import org.mockito.ArgumentMatchers; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; - import org.springframework.data.annotation.Id; import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.annotation.Transient; @@ -1217,7 +1216,7 @@ private static class Fixture { public void assertOn(T result) { - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { expectations.forEach(expectation -> { softly.assertThat(expectation.extractor.apply(result)).describedAs("From column: " + expectation.sourceColumn) diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/IdentifierUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/IdentifierUnitTests.java index 0eb94fd024..e395b7b52f 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/IdentifierUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/IdentifierUnitTests.java @@ -16,6 +16,7 @@ package org.springframework.data.jdbc.core.convert; import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.SoftAssertions.*; import static org.springframework.data.relational.core.sql.SqlIdentifier.*; import java.util.ArrayList; @@ -25,7 +26,6 @@ import java.util.Map; import org.assertj.core.api.Assertions; -import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; import org.springframework.data.relational.core.sql.IdentifierProcessing; import org.springframework.data.relational.core.sql.SqlIdentifier; @@ -125,7 +125,7 @@ public void identifierPartsCanBeAccessedByString() { Map map = id.toMap(); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(map.get("aName")).describedAs("aName").isEqualTo("one"); softly.assertThat(map.get("Other")).describedAs("Other").isEqualTo("two"); softly.assertThat(map.get("other")).describedAs("other").isNull(); diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorEmbeddedUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorEmbeddedUnitTests.java index 8f6ac02ca4..ec33659f32 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorEmbeddedUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorEmbeddedUnitTests.java @@ -17,8 +17,8 @@ import static java.util.Collections.*; import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.SoftAssertions.*; -import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -42,7 +42,7 @@ */ public class SqlGeneratorEmbeddedUnitTests { - private RelationalMappingContext context = new JdbcMappingContext(); + private final RelationalMappingContext context = new JdbcMappingContext(); JdbcConverter converter = new BasicJdbcConverter(context, (identifier, path) -> { throw new UnsupportedOperationException(); }); @@ -63,7 +63,7 @@ SqlGenerator createSqlGenerator(Class type) { public void findOne() { final String sql = sqlGenerator.getFindOne(); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(sql).startsWith("SELECT") // .contains("dummy_entity.id1 AS id1") // @@ -86,7 +86,7 @@ public void findOne() { public void findAll() { final String sql = sqlGenerator.getFindAll(); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(sql).startsWith("SELECT") // .contains("dummy_entity.id1 AS id1") // @@ -109,7 +109,7 @@ public void findAll() { public void findAllInList() { final String sql = sqlGenerator.getFindAllInList(); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(sql).startsWith("SELECT") // .contains("dummy_entity.id1 AS id1") // @@ -132,7 +132,7 @@ public void findAllInList() { public void insert() { final String sql = sqlGenerator.getInsert(emptySet()); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(sql) // .startsWith("INSERT INTO") // @@ -154,7 +154,7 @@ public void insert() { public void update() { final String sql = sqlGenerator.getUpdate(); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(sql) // .startsWith("UPDATE") // @@ -267,7 +267,7 @@ public void joinForEmbeddedWithReference() { SqlGenerator.Join join = generateJoin("embedded.other", DummyEntity2.class); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(join.getJoinTable().getName()).isEqualTo(SqlIdentifier.unquoted("other_entity")); softly.assertThat(join.getJoinColumn().getTable()).isEqualTo(join.getJoinTable()); diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorUnitTests.java index 01c390a680..d6e89bc745 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorUnitTests.java @@ -17,6 +17,7 @@ import static java.util.Collections.*; import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.SoftAssertions.*; import static org.springframework.data.relational.core.sql.SqlIdentifier.*; import java.util.Map; @@ -94,7 +95,7 @@ public void findOne() { String sql = sqlGenerator.getFindOne(); - SoftAssertions.assertSoftly(softly -> softly // + assertSoftly(softly -> softly // .assertThat(sql) // .startsWith("SELECT") // .contains("dummy_entity.id1 AS id1,") // @@ -113,7 +114,7 @@ public void getAcquireLockById() { String sql = sqlGenerator.getAcquireLockById(LockMode.PESSIMISTIC_WRITE); - SoftAssertions.assertSoftly(softly -> softly // + assertSoftly(softly -> softly // .assertThat(sql) // .startsWith("SELECT") // .contains("dummy_entity.id1") // @@ -127,7 +128,7 @@ public void getAcquireLockAll() { String sql = sqlGenerator.getAcquireLockAll(LockMode.PESSIMISTIC_WRITE); - SoftAssertions.assertSoftly(softly -> softly // + assertSoftly(softly -> softly // .assertThat(sql) // .startsWith("SELECT") // .contains("dummy_entity.id1") // @@ -580,7 +581,7 @@ public void joinForSimpleReference() { SqlGenerator.Join join = generateJoin("ref", DummyEntity.class); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(join.getJoinTable().getName()).isEqualTo(SqlIdentifier.quoted("REFERENCED_ENTITY")); softly.assertThat(join.getJoinColumn().getTable()).isEqualTo(join.getJoinTable()); @@ -612,7 +613,7 @@ public void joinForSecondLevelReference() { SqlGenerator.Join join = generateJoin("ref.further", DummyEntity.class); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(join.getJoinTable().getName()) .isEqualTo(SqlIdentifier.quoted("SECOND_LEVEL_REFERENCED_ENTITY")); @@ -629,7 +630,7 @@ public void joinForOneToOneWithoutId() { SqlGenerator.Join join = generateJoin("child", ParentOfNoIdChild.class); Table joinTable = join.getJoinTable(); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(joinTable.getName()).isEqualTo(SqlIdentifier.quoted("NO_ID_CHILD")); softly.assertThat(joinTable).isInstanceOf(Aliased.class); diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlIdentifierParameterSourceUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlIdentifierParameterSourceUnitTests.java index 88b5802486..bf3ba8973f 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlIdentifierParameterSourceUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlIdentifierParameterSourceUnitTests.java @@ -15,7 +15,8 @@ */ package org.springframework.data.jdbc.core.convert; -import org.assertj.core.api.SoftAssertions; +import static org.assertj.core.api.SoftAssertions.*; + import org.junit.jupiter.api.Test; import org.springframework.data.relational.core.sql.IdentifierProcessing; import org.springframework.data.relational.core.sql.SqlIdentifier; @@ -34,7 +35,7 @@ public void empty() { SqlIdentifierParameterSource parameters = new SqlIdentifierParameterSource(identifierProcessing); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(parameters.getParameterNames()).isEmpty(); softly.assertThat(parameters.getValue("blah")).isNull(); @@ -50,7 +51,7 @@ public void addSingleValue() { parameters.addValue(SqlIdentifier.unquoted("key"), 23); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(parameters.getParameterNames()).isEqualTo(new String[] { "key" }); softly.assertThat(parameters.getValue("key")).isEqualTo(23); @@ -69,7 +70,7 @@ public void addSingleValueWithType() { parameters.addValue(SqlIdentifier.unquoted("key"), 23, 42); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(parameters.getParameterNames()).isEqualTo(new String[] { "key" }); softly.assertThat(parameters.getValue("key")).isEqualTo(23); @@ -95,7 +96,7 @@ public void addOtherDatabaseObjectIdentifierParameterSource() { parameters.addAll(parameters2); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(parameters.getParameterNames()).isEqualTo(new String[] { "key1", "key2", "key3" }); softly.assertThat(parameters.getValue("key1")).isEqualTo(111); diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/dialect/JdbcDb2DialectUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/dialect/JdbcDb2DialectUnitTests.java new file mode 100644 index 0000000000..116d458daa --- /dev/null +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/dialect/JdbcDb2DialectUnitTests.java @@ -0,0 +1,46 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jdbc.core.dialect; + +import static org.assertj.core.api.SoftAssertions.*; + +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.springframework.data.jdbc.core.convert.JdbcCustomConversions; + +/** + * Tests for {@link JdbcMySqlDialect}. + * + * @author Jens Schauder + */ +class JdbcDb2DialectUnitTests { + + @Test // #974 + void testCustomConversions() { + + JdbcCustomConversions customConversions = new JdbcCustomConversions( + (List) JdbcDb2Dialect.INSTANCE.getConverters()); + + assertSoftly(softly -> { + softly.assertThat(customConversions.getCustomWriteTarget(LocalDateTime.class)).contains(Timestamp.class); + softly.assertThat(customConversions.getCustomWriteTarget(OffsetDateTime.class)).contains(Timestamp.class); + }); + } +} diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/dialect/JdbcMySqlDialectUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/dialect/JdbcMySqlDialectUnitTests.java new file mode 100644 index 0000000000..26c0e68759 --- /dev/null +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/dialect/JdbcMySqlDialectUnitTests.java @@ -0,0 +1,47 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jdbc.core.dialect; + +import static org.assertj.core.api.SoftAssertions.*; + +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.springframework.data.jdbc.core.convert.JdbcCustomConversions; +import org.springframework.data.jdbc.core.convert.JdbcValue; + +/** + * Tests for {@link JdbcMySqlDialect}. + * + * @author Jens Schauder + */ +class JdbcMySqlDialectUnitTests { + + @Test // #974 + void testCustomConversions() { + + JdbcCustomConversions customConversions = new JdbcCustomConversions( + (List) new JdbcMySqlDialect().getConverters()); + + assertSoftly(softly -> { + + softly.assertThat(customConversions.getCustomWriteTarget(LocalDateTime.class)).isEmpty(); + softly.assertThat(customConversions.getCustomWriteTarget(OffsetDateTime.class)).contains(JdbcValue.class); + }); + } +} diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/mapping/BasicJdbcPersistentPropertyUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/mapping/BasicJdbcPersistentPropertyUnitTests.java index 7a566a846d..8d613ee58c 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/mapping/BasicJdbcPersistentPropertyUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/mapping/BasicJdbcPersistentPropertyUnitTests.java @@ -16,6 +16,7 @@ package org.springframework.data.jdbc.core.mapping; import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.SoftAssertions.*; import static org.springframework.data.relational.core.sql.SqlIdentifier.*; import junit.framework.AssertionFailedError; @@ -27,7 +28,6 @@ import java.util.List; import java.util.UUID; -import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; import org.springframework.data.annotation.Id; import org.springframework.data.mapping.PersistentPropertyPath; @@ -101,7 +101,7 @@ void considersAggregateReferenceAnAssociation() { RelationalPersistentEntity entity = context.getRequiredPersistentEntity(DummyEntity.class); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(entity.getRequiredPersistentProperty("reference").isAssociation()) // .as("reference") // diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/mybatis/MyBatisContextUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/mybatis/MyBatisContextUnitTests.java index aa474739da..322dfa7f2b 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/mybatis/MyBatisContextUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/mybatis/MyBatisContextUnitTests.java @@ -15,10 +15,11 @@ */ package org.springframework.data.jdbc.mybatis; +import static org.assertj.core.api.SoftAssertions.*; + import java.util.HashMap; import java.util.Map; -import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; import org.springframework.data.jdbc.core.convert.Identifier; import org.springframework.data.relational.core.sql.SqlIdentifier; @@ -36,7 +37,7 @@ public void testGetReturnsValuesFromIdentifier() { MyBatisContext context = new MyBatisContext(Identifier.from(map), null, null); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(context.get("one")).isEqualTo("oneValue"); softly.assertThat(context.get("two")).isEqualTo("twoValue"); diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryCustomConversionIntegrationTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryCustomConversionIntegrationTests.java index 00e9fd8047..790154e7dd 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryCustomConversionIntegrationTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryCustomConversionIntegrationTests.java @@ -17,13 +17,13 @@ import static java.util.Arrays.*; import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.SoftAssertions.*; import static org.springframework.test.context.TestExecutionListeners.MergeMode.*; import java.math.BigDecimal; import java.sql.JDBCType; import java.util.Date; -import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -130,7 +130,7 @@ public void saveAndLoadAnEntityWithReference() { EntityWithStringyBigDecimal reloaded = repository.findById(entity.id).get(); // loading the number from the database might result in additional zeros at the end. - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { String stringyNumber = reloaded.stringyNumber; softly.assertThat(stringyNumber).startsWith(entity.stringyNumber); softly.assertThat(stringyNumber.substring(entity.stringyNumber.length())).matches("0*"); diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryIntegrationTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryIntegrationTests.java index 54497a5d44..4b878d6ce3 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryIntegrationTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryIntegrationTests.java @@ -27,6 +27,7 @@ import java.io.IOException; import java.sql.ResultSet; import java.time.Instant; +import java.time.LocalDateTime; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.util.ArrayList; @@ -49,6 +50,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; +import org.springframework.data.jdbc.repository.query.Modifying; import org.springframework.data.jdbc.repository.query.Query; import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory; import org.springframework.data.jdbc.testing.AssumeFeatureTestExecutionListener; @@ -492,6 +494,13 @@ public void pageQueryProjectionShouldReturnProjectedEntities() { assertThat(result.getContent().get(0).getName()).isEqualTo("Entity Name"); } + @Test // #974 + @EnabledOnFeature(TestDatabaseFeatures.Feature.IS_POSTGRES) + void intervalCalculation() { + + repository.updateWithIntervalCalculation(23L, LocalDateTime.now()); + } + private Instant createDummyBeforeAndAfterNow() { Instant now = Instant.now(); @@ -557,6 +566,10 @@ interface DummyEntityRepository extends CrudRepository { @Query("SELECT * FROM DUMMY_ENTITY WHERE OFFSET_DATE_TIME > :threshhold") List findByOffsetDateTime(@Param("threshhold") OffsetDateTime threshhold); + + @Modifying + @Query("UPDATE dummy_entity SET point_in_time = :start - interval '30 minutes' WHERE id_prop = :id") + void updateWithIntervalCalculation(@Param("id") Long id, @Param("start") LocalDateTime start); } @Configuration diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/QueryAnnotationHsqlIntegrationTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/QueryAnnotationHsqlIntegrationTests.java index f6abbbe705..b4acc943e9 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/QueryAnnotationHsqlIntegrationTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/QueryAnnotationHsqlIntegrationTests.java @@ -16,6 +16,7 @@ package org.springframework.data.jdbc.repository.query; import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.SoftAssertions.*; import lombok.Value; @@ -25,7 +26,6 @@ import java.util.Optional; import java.util.stream.Stream; -import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -192,7 +192,7 @@ public void executeCustomQueryWithReturnTypeIsBoolean() { repository.save(dummyEntity("bbb")); repository.save(dummyEntity("cac")); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(repository.existsByNameContaining("a")).describedAs("entities with A in the name").isTrue(); softly.assertThat(repository.existsByNameContaining("d")).describedAs("entities with D in the name").isFalse(); diff --git a/spring-data-relational/pom.xml b/spring-data-relational/pom.xml index 4e42a006ec..54e73ec98c 100644 --- a/spring-data-relational/pom.xml +++ b/spring-data-relational/pom.xml @@ -6,7 +6,7 @@ 4.0.0 spring-data-relational - 2.3.0-SNAPSHOT + 2.3.0-974-no-conversion-to-timestamp-for-postgres-SNAPSHOT Spring Data Relational Spring Data Relational support @@ -14,7 +14,7 @@ org.springframework.data spring-data-relational-parent - 2.3.0-SNAPSHOT + 2.3.0-974-no-conversion-to-timestamp-for-postgres-SNAPSHOT diff --git a/spring-data-relational/src/test/java/org/springframework/data/relational/core/mapping/DerivedSqlIdentifierUnitTests.java b/spring-data-relational/src/test/java/org/springframework/data/relational/core/mapping/DerivedSqlIdentifierUnitTests.java index e001f3bf41..45788a96d9 100644 --- a/spring-data-relational/src/test/java/org/springframework/data/relational/core/mapping/DerivedSqlIdentifierUnitTests.java +++ b/spring-data-relational/src/test/java/org/springframework/data/relational/core/mapping/DerivedSqlIdentifierUnitTests.java @@ -16,10 +16,9 @@ package org.springframework.data.relational.core.mapping; import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.SoftAssertions.*; -import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; - import org.springframework.data.relational.core.sql.IdentifierProcessing; import org.springframework.data.relational.core.sql.IdentifierProcessing.LetterCasing; import org.springframework.data.relational.core.sql.IdentifierProcessing.Quoting; @@ -75,7 +74,7 @@ public void equality() { SqlIdentifier notSimple = SqlIdentifier.from(new DerivedSqlIdentifier("simple", false), new DerivedSqlIdentifier("not", false)); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(basis).isEqualTo(equal); softly.assertThat(equal).isEqualTo(basis); diff --git a/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/SqlIdentifierUnitTests.java b/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/SqlIdentifierUnitTests.java index 8eadf7c03d..a01bf854ff 100644 --- a/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/SqlIdentifierUnitTests.java +++ b/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/SqlIdentifierUnitTests.java @@ -16,11 +16,10 @@ package org.springframework.data.relational.core.sql; import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.SoftAssertions.*; import static org.springframework.data.relational.core.sql.SqlIdentifier.*; -import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; - import org.springframework.data.relational.core.sql.IdentifierProcessing.LetterCasing; import org.springframework.data.relational.core.sql.IdentifierProcessing.Quoting; @@ -80,7 +79,7 @@ public void equality() { SqlIdentifier quoted = quoted("simple"); SqlIdentifier notSimple = SqlIdentifier.from(unquoted("simple"), unquoted("not")); - SoftAssertions.assertSoftly(softly -> { + assertSoftly(softly -> { softly.assertThat(basis).isEqualTo(equal); softly.assertThat(equal).isEqualTo(basis);