Do not convert from LocalDateTime to Timestamp by default.

Most supported databases don't need that conversion.

Db2 does need it and gets it through JdbcDb2Dialect.

As part of the effort it became obvious that the filtering for conversions between Date and JSR310 data types was broken.
It is fixed now, which required a dedicated reading conversion from LocalDateTime to Date for JdbcMySqlDialect.

Closes #974
Original pull request: #985.
This commit is contained in:
Jens Schauder
2021-06-07 13:52:42 +02:00
committed by Mark Paluch
parent 2c413a2d3b
commit 8652418245
22 changed files with 217 additions and 67 deletions

View File

@@ -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 enum JdbcColumnTypes {
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);
}

View File

@@ -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 @@ import org.springframework.data.jdbc.core.mapping.JdbcSimpleTypes;
*/
public class JdbcCustomConversions extends CustomConversions {
private static final Collection<Object> STORE_CONVERTERS = Collections.unmodifiableCollection(Jsr310TimestampBasedConverters.getConvertersToRegister());
private static final Collection<Object> STORE_CONVERTERS = Collections
.unmodifiableCollection(Jsr310TimestampBasedConverters.getConvertersToRegister());
private static final StoreConversions STORE_CONVERSIONS = StoreConversions.of(JdbcSimpleTypes.HOLDER,
STORE_CONVERTERS);
@@ -50,21 +49,33 @@ public class JdbcCustomConversions extends CustomConversions {
}
/**
* 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 @@ public class JdbcCustomConversions extends CustomConversions {
return cp.getSourceType().getTypeName().startsWith("java.time.");
}
return true;
return false;
}
private static boolean excludeConversionsBetweenDateAndJsr310Types(ConvertiblePair cp) {
return !isDateTimeApiConversion(cp);
}
}

View File

@@ -45,22 +45,21 @@ import org.springframework.lang.NonNull;
* @author Jens Schauder
* @since 2.2
*/
abstract class Jsr310TimestampBasedConverters {
private static final List<Class<?>> 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.
*
* @return
* 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 a collection of converters. Guaranteed to be not {@literal null}.
*/
public static Collection<Converter<?, ?>> getConvertersToRegister() {
List<Converter<?, ?>> converters = new ArrayList<>(8);
converters.add(TimestampToLocalDateTimeConverter.INSTANCE);
converters.add(LocalDateTimeToTimestampConverter.INSTANCE);
converters.add(TimestampToLocalDateConverter.INSTANCE);
converters.add(LocalDateToTimestampConverter.INSTANCE);
converters.add(TimestampToLocalTimeConverter.INSTANCE);

View File

@@ -23,6 +23,7 @@ import java.util.List;
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 class JdbcDb2Dialect extends Db2Dialect {
List<Object> converters = new ArrayList<>(super.getConverters());
converters.add(OffsetDateTimeToTimestampConverter.INSTANCE);
converters.add(Jsr310TimestampBasedConverters.LocalDateTimeToTimestampConverter.INSTANCE);
return converters;
}

View File

@@ -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 class JdbcMySqlDialect extends MySqlDialect {
ArrayList<Object> converters = new ArrayList<>(super.getConverters());
converters.add(OffsetDateTimeToTimestampJdbcValueConverter.INSTANCE);
converters.add(LocalDateTimeToDateConverter.INSTANCE);
return converters;
}
@@ -61,4 +68,16 @@ public class JdbcMySqlDialect extends MySqlDialect {
return JdbcValue.of(source, JDBCType.TIMESTAMP);
}
}
@ReadingConverter
enum LocalDateTimeToDateConverter implements Converter<LocalDateTime, Date> {
INSTANCE;
@NonNull
@Override
public Date convert(LocalDateTime source) {
return Date.from(source.atZone(systemDefault()).toInstant());
}
}
}

View File

@@ -17,6 +17,7 @@ package org.springframework.data.jdbc.core;
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.List;
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 class AggregateChangeIdGenerationUnitTests {
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 class AggregateChangeIdGenerationUnitTests {
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 class AggregateChangeIdGenerationUnitTests {
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 class AggregateChangeIdGenerationUnitTests {
executor.execute(aggregateChange);
SoftAssertions.assertSoftly(softly -> {
assertSoftly(softly -> {
softly.assertThat(entity.rootId).isEqualTo(1);
softly.assertThat(entity.contentSet) //
@@ -233,7 +233,7 @@ public class AggregateChangeIdGenerationUnitTests {
executor.execute(aggregateChange);
SoftAssertions.assertSoftly(softly -> {
assertSoftly(softly -> {
softly.assertThat(entity.rootId).isEqualTo(1);
softly.assertThat(entity.contentList) //
@@ -267,7 +267,7 @@ public class AggregateChangeIdGenerationUnitTests {
executor.execute(aggregateChange);
SoftAssertions.assertSoftly(softly -> {
assertSoftly(softly -> {
softly.assertThat(entity.rootId).isEqualTo(1);
softly.assertThat(entity.contentList) //
@@ -305,7 +305,7 @@ public class AggregateChangeIdGenerationUnitTests {
executor.execute(aggregateChange);
SoftAssertions.assertSoftly(softly -> {
assertSoftly(softly -> {
softly.assertThat(entity.rootId).isEqualTo(1);
softly.assertThat(entity.contentMap.entrySet()) //

View File

@@ -17,6 +17,7 @@ package org.springframework.data.jdbc.core;
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 class JdbcAggregateTemplateIntegrationTests {
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 class JdbcAggregateTemplateIntegrationTests {
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);

View File

@@ -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.Instant;
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 class BasicJdbcConverterUnitTests {
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 @@ public class BasicJdbcConverterUnitTests {
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 @@ public class BasicJdbcConverterUnitTests {
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<DummyEntity, Long> reference;
private final UUID uuid;

View File

@@ -18,6 +18,7 @@ package org.springframework.data.jdbc.core.convert;
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 java.util.stream.Stream;
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 @@ public class EntityRowMapperUnitTests {
public void assertOn(T result) {
SoftAssertions.assertSoftly(softly -> {
assertSoftly(softly -> {
expectations.forEach(expectation -> {
softly.assertThat(expectation.extractor.apply(result)).describedAs("From column: " + expectation.sourceColumn)

View File

@@ -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.List;
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 class IdentifierUnitTests {
Map<SqlIdentifier, Object> 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();

View File

@@ -17,8 +17,8 @@ package org.springframework.data.jdbc.core.convert;
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 @@ import org.springframework.lang.Nullable;
*/
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 @@ public class SqlGeneratorEmbeddedUnitTests {
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 class SqlGeneratorEmbeddedUnitTests {
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 class SqlGeneratorEmbeddedUnitTests {
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 class SqlGeneratorEmbeddedUnitTests {
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 class SqlGeneratorEmbeddedUnitTests {
public void update() {
final String sql = sqlGenerator.getUpdate();
SoftAssertions.assertSoftly(softly -> {
assertSoftly(softly -> {
softly.assertThat(sql) //
.startsWith("UPDATE") //
@@ -267,7 +267,7 @@ public class SqlGeneratorEmbeddedUnitTests {
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());

View File

@@ -17,6 +17,7 @@ package org.springframework.data.jdbc.core.convert;
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 class SqlGeneratorUnitTests {
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 class SqlGeneratorUnitTests {
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 class SqlGeneratorUnitTests {
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 class SqlGeneratorUnitTests {
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 class SqlGeneratorUnitTests {
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 class SqlGeneratorUnitTests {
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);

View File

@@ -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 class SqlIdentifierParameterSourceUnitTests {
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 class SqlIdentifierParameterSourceUnitTests {
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 class SqlIdentifierParameterSourceUnitTests {
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 class SqlIdentifierParameterSourceUnitTests {
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);

View File

@@ -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);
});
}
}

View File

@@ -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);
});
}
}

View File

@@ -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.Date;
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 @@ public class BasicJdbcPersistentPropertyUnitTests {
RelationalPersistentEntity<?> entity = context.getRequiredPersistentEntity(DummyEntity.class);
SoftAssertions.assertSoftly(softly -> {
assertSoftly(softly -> {
softly.assertThat(entity.getRequiredPersistentProperty("reference").isAssociation()) //
.as("reference") //

View File

@@ -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 class MyBatisContextUnitTests {
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");

View File

@@ -17,13 +17,13 @@ package org.springframework.data.jdbc.repository;
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 class JdbcRepositoryCustomConversionIntegrationTests {
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*");

View File

@@ -27,6 +27,7 @@ import lombok.Value;
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.Page;
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 class JdbcRepositoryIntegrationTests {
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 @@ public class JdbcRepositoryIntegrationTests {
@Query("SELECT * FROM DUMMY_ENTITY WHERE OFFSET_DATE_TIME > :threshhold")
List<DummyEntity> 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

View File

@@ -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.List;
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 class QueryAnnotationHsqlIntegrationTests {
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();

View File

@@ -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 class DerivedSqlIdentifierUnitTests {
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);

View File

@@ -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 class SqlIdentifierUnitTests {
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);