#207 - Skip converter registrations for JSR-310 to java.util.Date.
We now prevent converter registrations that enforce a conversion from JSR-310 types to java.util.Date. R2DBC drivers use natively JSR-310 types and some of them don't implement java.util.Date at all.
This commit is contained in:
@@ -3,6 +3,7 @@ package org.springframework.data.r2dbc.convert;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
@@ -40,7 +41,7 @@ public class R2dbcCustomConversions extends CustomConversions {
|
||||
* @param converters must not be {@literal null}.
|
||||
*/
|
||||
public R2dbcCustomConversions(Collection<?> converters) {
|
||||
super(STORE_CONVERSIONS, appendOverrides(converters));
|
||||
super(new R2dbcCustomConversionsConfiguration(STORE_CONVERSIONS, appendOverrides(converters)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,14 +51,29 @@ public class R2dbcCustomConversions extends CustomConversions {
|
||||
* @param converters must not be {@literal null}.
|
||||
*/
|
||||
public R2dbcCustomConversions(StoreConversions storeConversions, Collection<?> converters) {
|
||||
super(storeConversions, appendOverrides(converters));
|
||||
super(new R2dbcCustomConversionsConfiguration(storeConversions, appendOverrides(converters)));
|
||||
}
|
||||
|
||||
private static Collection<?> appendOverrides(Collection<?> converters) {
|
||||
private static List<?> appendOverrides(Collection<?> converters) {
|
||||
|
||||
List<Object> objects = new ArrayList<>(converters);
|
||||
objects.addAll(R2dbcConverters.getOverrideConvertersToRegister());
|
||||
|
||||
return objects;
|
||||
}
|
||||
|
||||
static class R2dbcCustomConversionsConfiguration extends ConverterConfiguration {
|
||||
|
||||
public R2dbcCustomConversionsConfiguration(StoreConversions storeConversions, List<?> userConverters) {
|
||||
super(storeConversions, userConverters, convertiblePair -> {
|
||||
|
||||
if (convertiblePair.getSourceType().getName().startsWith("java.time.")
|
||||
&& convertiblePair.getTargetType().equals(Date.class)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ import static org.mockito.Mockito.*;
|
||||
import io.r2dbc.spi.Row;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
@@ -61,17 +63,21 @@ public class MappingR2dbcConverterUnitTests {
|
||||
converter = new MappingR2dbcConverter(mappingContext, conversions);
|
||||
}
|
||||
|
||||
@Test // gh-61
|
||||
@Test // gh-61, gh-207
|
||||
public void shouldIncludeAllPropertiesInOutboundRow() {
|
||||
|
||||
OutboundRow row = new OutboundRow();
|
||||
|
||||
converter.write(new Person("id", "Walter", "White"), row);
|
||||
Instant instant = Instant.now();
|
||||
LocalDateTime localDateTime = LocalDateTime.now();
|
||||
converter.write(new Person("id", "Walter", "White", instant, localDateTime), row);
|
||||
|
||||
assertThat(row).containsEntry(SqlIdentifier.unquoted("id"), SettableValue.fromOrEmpty("id", String.class));
|
||||
assertThat(row).containsEntry(SqlIdentifier.unquoted("firstname"),
|
||||
SettableValue.fromOrEmpty("Walter", String.class));
|
||||
assertThat(row).containsEntry(SqlIdentifier.unquoted("lastname"), SettableValue.fromOrEmpty("White", String.class));
|
||||
assertThat(row).containsEntry(SqlIdentifier.unquoted("instant"), SettableValue.from(instant));
|
||||
assertThat(row).containsEntry(SqlIdentifier.unquoted("local_date_time"), SettableValue.from(localDateTime));
|
||||
}
|
||||
|
||||
@Test // gh-41
|
||||
@@ -187,6 +193,8 @@ public class MappingR2dbcConverterUnitTests {
|
||||
static class Person {
|
||||
@Id String id;
|
||||
String firstname, lastname;
|
||||
Instant instant;
|
||||
LocalDateTime localDateTime;
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
|
||||
@@ -16,23 +16,34 @@
|
||||
package org.springframework.data.r2dbc.repository;
|
||||
|
||||
import io.r2dbc.spi.ConnectionFactory;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration;
|
||||
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
|
||||
import org.springframework.data.r2dbc.repository.support.R2dbcRepositoryFactory;
|
||||
import org.springframework.data.r2dbc.testing.ExternalDatabase;
|
||||
import org.springframework.data.r2dbc.testing.MySqlTestSupport;
|
||||
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@@ -47,9 +58,12 @@ public class MySqlR2dbcRepositoryIntegrationTests extends AbstractR2dbcRepositor
|
||||
|
||||
@ClassRule public static final ExternalDatabase database = MySqlTestSupport.database();
|
||||
|
||||
@Autowired DateTestsRepository dateTestsRepository;
|
||||
|
||||
@Configuration
|
||||
@EnableR2dbcRepositories(considerNestedRepositories = true,
|
||||
includeFilters = @Filter(classes = MySqlLegoSetRepository.class, type = FilterType.ASSIGNABLE_TYPE))
|
||||
includeFilters = { @Filter(classes = MySqlLegoSetRepository.class, type = FilterType.ASSIGNABLE_TYPE),
|
||||
@Filter(classes = DateTestsRepository.class, type = FilterType.ASSIGNABLE_TYPE) })
|
||||
static class IntegrationTestConfiguration extends AbstractR2dbcConfiguration {
|
||||
|
||||
@Bean
|
||||
@@ -79,6 +93,29 @@ public class MySqlR2dbcRepositoryIntegrationTests extends AbstractR2dbcRepositor
|
||||
return MySqlLegoSetRepository.class;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldUserJsr310Types() {
|
||||
|
||||
JdbcTemplate jdbcTemplate = createJdbcTemplate(createDataSource());
|
||||
|
||||
try {
|
||||
jdbcTemplate.execute("DROP TABLE date_tests");
|
||||
} catch (DataAccessException e) {}
|
||||
|
||||
jdbcTemplate.execute("CREATE TABLE date_tests (id int, created_timestamp TIMESTAMP, created_date datetime);");
|
||||
|
||||
dateTestsRepository.save(new DateTests(null, LocalDateTime.now(), LocalDateTime.now())).as(StepVerifier::create)
|
||||
.expectNextCount(1).verifyComplete();
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
static class DateTests {
|
||||
@Id Integer id;
|
||||
LocalDateTime createdTimestamp;
|
||||
LocalDateTime createdDate;
|
||||
}
|
||||
|
||||
interface MySqlLegoSetRepository extends LegoSetRepository {
|
||||
|
||||
@Override
|
||||
@@ -93,4 +130,8 @@ public class MySqlR2dbcRepositoryIntegrationTests extends AbstractR2dbcRepositor
|
||||
@Query("SELECT id FROM legoset")
|
||||
Flux<Integer> findAllIds();
|
||||
}
|
||||
|
||||
interface DateTestsRepository extends ReactiveCrudRepository<DateTests, Integer> {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user