From a1c2b42b101c0db2b30dedb4fb1ed5a75281a3c6 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Wed, 1 Nov 2017 12:42:22 +0100 Subject: [PATCH 1/2] DATAJDBC-147 - Prepare branch --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7fc8f36b75..758ca56e8a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.data spring-data-jdbc - 1.0.0.BUILD-SNAPSHOT + 1.0.0.DATAJDBC-147-SNAPSHOT Spring Data JDBC Spring Data module for JDBC repositories. From bea451a61ef94d7bc1d7c4dba705be4195469006 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Wed, 1 Nov 2017 14:37:40 +0100 Subject: [PATCH 2/2] DATAJDBC-147 - Support registration von converters via ConversionCustomizers. --- .../jdbc/core/DefaultDataAccessStrategy.java | 17 +-------- .../mapping/model/ConversionCustomizer.java | 26 +++++++++++++ .../mapping/model/JdbcMappingContext.java | 26 ++++++++++++- .../support/JdbcRepositoryFactoryBean.java | 20 +++++++--- .../jdbc/core/EntityRowMapperUnitTests.java | 3 +- .../JdbcEntityTemplateIntegrationTests.java | 3 +- ...orContextBasedNamingStrategyUnitTests.java | 2 +- ...GeneratorFixedNamingStrategyUnitTests.java | 2 +- .../data/jdbc/core/SqlGeneratorUnitTests.java | 2 +- .../JdbcEntityDeleteWriterUnitTests.java | 3 +- .../conversion/JdbcEntityWriterUnitTests.java | 3 +- .../BasicJdbcPersistentPropertyUnitTests.java | 2 +- .../SimpleJdbcRepositoryEventsUnitTests.java | 3 +- .../JdbcRepositoryFactoryBeanUnitTests.java | 37 +++++++++++++++++++ .../data/jdbc/testing/TestConfiguration.java | 4 +- 15 files changed, 116 insertions(+), 37 deletions(-) create mode 100644 src/main/java/org/springframework/data/jdbc/mapping/model/ConversionCustomizer.java diff --git a/src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java b/src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java index 9cba047827..a6e5da025f 100644 --- a/src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java +++ b/src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java @@ -21,13 +21,9 @@ import java.util.stream.Collectors; import java.util.stream.StreamSupport; -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.support.DefaultConversionService; -import org.springframework.core.convert.support.GenericConversionService; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.dao.NonTransientDataAccessException; -import org.springframework.data.convert.Jsr310Converters; import org.springframework.data.jdbc.mapping.model.BasicJdbcPersistentEntityInformation; import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; import org.springframework.data.jdbc.mapping.model.JdbcPersistentEntity; @@ -58,7 +54,6 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy { private final SqlGeneratorSource sqlGeneratorSource; private final NamedParameterJdbcOperations operations; private final JdbcMappingContext context; - private final ConversionService conversions = getDefaultConversionService(); private final DataAccessStrategy accessStrategy; public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, NamedParameterJdbcOperations operations, @@ -215,14 +210,6 @@ public boolean existsById(Object id, Class domainType) { return operations.queryForObject(existsSql, parameter, Boolean.class); } - private static GenericConversionService getDefaultConversionService() { - - DefaultConversionService conversionService = new DefaultConversionService(); - Jsr310Converters.getConvertersToRegister().forEach(conversionService::addConverter); - - return conversionService; - } - private MapSqlParameterSource getPropertyMap(final S instance, JdbcPersistentEntity persistentEntity) { MapSqlParameterSource parameters = new MapSqlParameterSource(); @@ -288,7 +275,7 @@ private Optional getIdFromHolder(KeyHolder holder, JdbcPersistentEnt } private EntityRowMapper getEntityRowMapper(Class domainType) { - return new EntityRowMapper<>(getRequiredPersistentEntity(domainType), conversions, context, accessStrategy); + return new EntityRowMapper<>(getRequiredPersistentEntity(domainType), context.getConversions(), context, accessStrategy); } private RowMapper getMapEntityRowMapper(JdbcPersistentProperty property) { @@ -316,7 +303,7 @@ private V convert(Object from, Class to) { Object id = persistentEntity == null ? null : persistentEntity.getIdentifierAccessor(from).getIdentifier(); - return conversions.convert(id == null ? from : id, to); + return context.getConversions().convert(id == null ? from : id, to); } private SqlGenerator sql(Class domainType) { diff --git a/src/main/java/org/springframework/data/jdbc/mapping/model/ConversionCustomizer.java b/src/main/java/org/springframework/data/jdbc/mapping/model/ConversionCustomizer.java new file mode 100644 index 0000000000..c562cab2fc --- /dev/null +++ b/src/main/java/org/springframework/data/jdbc/mapping/model/ConversionCustomizer.java @@ -0,0 +1,26 @@ +/* + * Copyright 2017 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 + * + * http://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.mapping.model; + +import org.springframework.core.convert.support.GenericConversionService; + +/** + * @author Jens Schauder + */ +public interface ConversionCustomizer { + + void customize(GenericConversionService conversions); +} diff --git a/src/main/java/org/springframework/data/jdbc/mapping/model/JdbcMappingContext.java b/src/main/java/org/springframework/data/jdbc/mapping/model/JdbcMappingContext.java index 0d8ae2d80f..ebd9de1e60 100644 --- a/src/main/java/org/springframework/data/jdbc/mapping/model/JdbcMappingContext.java +++ b/src/main/java/org/springframework/data/jdbc/mapping/model/JdbcMappingContext.java @@ -27,6 +27,10 @@ import java.util.HashSet; import java.util.List; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.support.DefaultConversionService; +import org.springframework.core.convert.support.GenericConversionService; +import org.springframework.data.convert.Jsr310Converters; import org.springframework.data.mapping.PropertyPath; import org.springframework.data.mapping.context.AbstractMappingContext; import org.springframework.data.mapping.context.MappingContext; @@ -50,13 +54,21 @@ public class JdbcMappingContext extends AbstractMappingContext {}); + } + public List referencedEntities(Class rootType, PropertyPath path) { List paths = new ArrayList<>(); @@ -103,4 +115,16 @@ protected JdbcPersistentProperty createPersistentProperty(Property property, Jdb return new BasicJdbcPersistentEntityInformation<>((JdbcPersistentEntity) getRequiredPersistentEntity(type)); } + public ConversionService getConversions() { + return conversions; + } + + private static GenericConversionService getDefaultConversionService() { + + DefaultConversionService conversionService = new DefaultConversionService(); + Jsr310Converters.getConvertersToRegister().forEach(conversionService::addConverter); + + return conversionService; + } + } diff --git a/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java b/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java index 942efe12a0..cb717b3368 100644 --- a/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java +++ b/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java @@ -32,6 +32,7 @@ import org.springframework.data.jdbc.core.DefaultDataAccessStrategy; import org.springframework.data.jdbc.core.DelegatingDataAccessStrategy; import org.springframework.data.jdbc.core.SqlGeneratorSource; +import org.springframework.data.jdbc.mapping.model.ConversionCustomizer; import org.springframework.data.jdbc.mapping.model.DefaultNamingStrategy; import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; import org.springframework.data.jdbc.mapping.model.NamingStrategy; @@ -65,22 +66,23 @@ public class JdbcRepositoryFactoryBean, S, ID extend private static final String DATA_SOURCE_BEAN_NAME = "dataSource"; private static final String NAMING_STRATEGY_BEAN_NAME = "namingStrategy"; private static final String SQL_SESSION_FACTORY_BEAN_NAME = "sqlSessionFactory"; + private static final String CONVERSION_CUSTOMIZER_BEAN_NAME = "conversionCustomizer"; private final ApplicationEventPublisher applicationEventPublisher; - private final ApplicationContext context; + private final ApplicationContext applicationContext; JdbcRepositoryFactoryBean(Class repositoryInterface, ApplicationEventPublisher applicationEventPublisher, - ApplicationContext context) { + ApplicationContext applicationContext) { super(repositoryInterface); this.applicationEventPublisher = applicationEventPublisher; - this.context = context; + this.applicationContext = applicationContext; } @Override protected RepositoryFactorySupport doCreateRepositoryFactory() { - final JdbcMappingContext context = new JdbcMappingContext(findOrCreateNamingStrategy()); + final JdbcMappingContext context = new JdbcMappingContext(findOrCreateNamingStrategy(), findOrCreateConversionCustomizer()); return new JdbcRepositoryFactory(applicationEventPublisher, context, createDataAccessStrategy(context)); } @@ -156,6 +158,10 @@ private NamingStrategy findOrCreateNamingStrategy() { return getNamingStrategy().orElse(new DefaultNamingStrategy()); } + private ConversionCustomizer findOrCreateConversionCustomizer() { + return getConversionCustomizer().orElse(conversionService->{}); + } + private Optional getNamedParameterJdbcOperations() { return getBean(NamedParameterJdbcOperations.class, NAMED_PARAMETER_JDBC_OPERATIONS_BEAN_NAME); } @@ -172,9 +178,13 @@ private Optional getNamingStrategy() { return getBean(NamingStrategy.class, NAMING_STRATEGY_BEAN_NAME); } + private Optional getConversionCustomizer() { + return getBean(ConversionCustomizer.class, CONVERSION_CUSTOMIZER_BEAN_NAME); + } + private Optional getBean(Class type, String name) { - Map beansOfType = context.getBeansOfType(type); + Map beansOfType = applicationContext.getBeansOfType(type); if (beansOfType.size() == 1) { return beansOfType.values().stream().findFirst(); diff --git a/src/test/java/org/springframework/data/jdbc/core/EntityRowMapperUnitTests.java b/src/test/java/org/springframework/data/jdbc/core/EntityRowMapperUnitTests.java index 0385c15aef..09201b53d7 100644 --- a/src/test/java/org/springframework/data/jdbc/core/EntityRowMapperUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/core/EntityRowMapperUnitTests.java @@ -40,7 +40,6 @@ import org.springframework.core.convert.support.GenericConversionService; import org.springframework.data.annotation.Id; import org.springframework.data.convert.Jsr310Converters; -import org.springframework.data.jdbc.mapping.model.DefaultNamingStrategy; import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; import org.springframework.data.jdbc.mapping.model.JdbcPersistentEntity; import org.springframework.data.jdbc.mapping.model.JdbcPersistentProperty; @@ -118,7 +117,7 @@ public void mapReferenceGetsLoadedWithAdditionalSelect() throws SQLException { private EntityRowMapper createRowMapper(Class type) { - JdbcMappingContext context = new JdbcMappingContext(new DefaultNamingStrategy()); + JdbcMappingContext context = new JdbcMappingContext(); DataAccessStrategy accessStrategy = mock(DataAccessStrategy.class); // the ID of the entity is used to determin what kind of resultset is needed for subsequent selects. diff --git a/src/test/java/org/springframework/data/jdbc/core/JdbcEntityTemplateIntegrationTests.java b/src/test/java/org/springframework/data/jdbc/core/JdbcEntityTemplateIntegrationTests.java index fda034367f..87f2bce06e 100644 --- a/src/test/java/org/springframework/data/jdbc/core/JdbcEntityTemplateIntegrationTests.java +++ b/src/test/java/org/springframework/data/jdbc/core/JdbcEntityTemplateIntegrationTests.java @@ -30,7 +30,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.data.annotation.Id; -import org.springframework.data.jdbc.mapping.model.DefaultNamingStrategy; import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; import org.springframework.data.jdbc.testing.TestConfiguration; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; @@ -254,7 +253,7 @@ Class testClass() { JdbcEntityOperations operations(ApplicationEventPublisher publisher, NamedParameterJdbcOperations namedParameterJdbcOperations) { - final JdbcMappingContext context = new JdbcMappingContext(new DefaultNamingStrategy()); + final JdbcMappingContext context = new JdbcMappingContext(); return new JdbcEntityTemplate(publisher, context, dataAccessStrategy(namedParameterJdbcOperations, context)); } diff --git a/src/test/java/org/springframework/data/jdbc/core/SqlGeneratorContextBasedNamingStrategyUnitTests.java b/src/test/java/org/springframework/data/jdbc/core/SqlGeneratorContextBasedNamingStrategyUnitTests.java index 36f05af197..96020cbb8a 100644 --- a/src/test/java/org/springframework/data/jdbc/core/SqlGeneratorContextBasedNamingStrategyUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/core/SqlGeneratorContextBasedNamingStrategyUnitTests.java @@ -185,7 +185,7 @@ private void threadedTest(String user, CountDownLatch latch, Consumer te */ private SqlGenerator configureSqlGenerator(NamingStrategy namingStrategy) { - JdbcMappingContext context = new JdbcMappingContext(namingStrategy); + JdbcMappingContext context = new JdbcMappingContext(namingStrategy, __ -> {}); JdbcPersistentEntity persistentEntity = context.getRequiredPersistentEntity(DummyEntity.class); return new SqlGenerator(context, persistentEntity, new SqlGeneratorSource(context)); diff --git a/src/test/java/org/springframework/data/jdbc/core/SqlGeneratorFixedNamingStrategyUnitTests.java b/src/test/java/org/springframework/data/jdbc/core/SqlGeneratorFixedNamingStrategyUnitTests.java index 733ad5be87..12403a90fe 100644 --- a/src/test/java/org/springframework/data/jdbc/core/SqlGeneratorFixedNamingStrategyUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/core/SqlGeneratorFixedNamingStrategyUnitTests.java @@ -180,7 +180,7 @@ public void deleteByList() { */ private SqlGenerator configureSqlGenerator(NamingStrategy namingStrategy) { - JdbcMappingContext context = new JdbcMappingContext(namingStrategy); + JdbcMappingContext context = new JdbcMappingContext(namingStrategy, __ -> {}); JdbcPersistentEntity persistentEntity = context.getRequiredPersistentEntity(DummyEntity.class); return new SqlGenerator(context, persistentEntity, new SqlGeneratorSource(context)); } diff --git a/src/test/java/org/springframework/data/jdbc/core/SqlGeneratorUnitTests.java b/src/test/java/org/springframework/data/jdbc/core/SqlGeneratorUnitTests.java index 47f905380c..68ae221666 100644 --- a/src/test/java/org/springframework/data/jdbc/core/SqlGeneratorUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/core/SqlGeneratorUnitTests.java @@ -46,7 +46,7 @@ public class SqlGeneratorUnitTests { public void setUp() { NamingStrategy namingStrategy = new PrefixingNamingStrategy(); - JdbcMappingContext context = new JdbcMappingContext(namingStrategy); + JdbcMappingContext context = new JdbcMappingContext(namingStrategy, __ -> {}); JdbcPersistentEntity persistentEntity = context.getRequiredPersistentEntity(DummyEntity.class); this.sqlGenerator = new SqlGenerator(context, persistentEntity, new SqlGeneratorSource(context)); } diff --git a/src/test/java/org/springframework/data/jdbc/core/conversion/JdbcEntityDeleteWriterUnitTests.java b/src/test/java/org/springframework/data/jdbc/core/conversion/JdbcEntityDeleteWriterUnitTests.java index 4f66b36fd2..f84b23d8b7 100644 --- a/src/test/java/org/springframework/data/jdbc/core/conversion/JdbcEntityDeleteWriterUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/core/conversion/JdbcEntityDeleteWriterUnitTests.java @@ -25,7 +25,6 @@ import org.springframework.data.annotation.Id; import org.springframework.data.jdbc.core.conversion.AggregateChange.Kind; import org.springframework.data.jdbc.core.conversion.DbAction.Delete; -import org.springframework.data.jdbc.mapping.model.DefaultNamingStrategy; import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; /** @@ -36,7 +35,7 @@ @RunWith(MockitoJUnitRunner.class) public class JdbcEntityDeleteWriterUnitTests { - JdbcEntityDeleteWriter converter = new JdbcEntityDeleteWriter(new JdbcMappingContext(new DefaultNamingStrategy())); + JdbcEntityDeleteWriter converter = new JdbcEntityDeleteWriter(new JdbcMappingContext()); @Test public void deleteDeletesTheEntityAndReferencedEntities() { diff --git a/src/test/java/org/springframework/data/jdbc/core/conversion/JdbcEntityWriterUnitTests.java b/src/test/java/org/springframework/data/jdbc/core/conversion/JdbcEntityWriterUnitTests.java index 64b3ff5a37..8866e2a94e 100644 --- a/src/test/java/org/springframework/data/jdbc/core/conversion/JdbcEntityWriterUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/core/conversion/JdbcEntityWriterUnitTests.java @@ -32,7 +32,6 @@ import org.springframework.data.jdbc.core.conversion.DbAction.Delete; import org.springframework.data.jdbc.core.conversion.DbAction.Insert; import org.springframework.data.jdbc.core.conversion.DbAction.Update; -import org.springframework.data.jdbc.mapping.model.DefaultNamingStrategy; import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; /** @@ -44,7 +43,7 @@ public class JdbcEntityWriterUnitTests { public static final long SOME_ENTITY_ID = 23L; - JdbcEntityWriter converter = new JdbcEntityWriter(new JdbcMappingContext(new DefaultNamingStrategy())); + JdbcEntityWriter converter = new JdbcEntityWriter(new JdbcMappingContext()); @Test // DATAJDBC-112 public void newEntityGetsConvertedToOneInsert() { diff --git a/src/test/java/org/springframework/data/jdbc/mapping/model/BasicJdbcPersistentPropertyUnitTests.java b/src/test/java/org/springframework/data/jdbc/mapping/model/BasicJdbcPersistentPropertyUnitTests.java index ce9bf881e4..377370d763 100644 --- a/src/test/java/org/springframework/data/jdbc/mapping/model/BasicJdbcPersistentPropertyUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/mapping/model/BasicJdbcPersistentPropertyUnitTests.java @@ -37,7 +37,7 @@ public class BasicJdbcPersistentPropertyUnitTests { @Test // DATAJDBC-104 public void enumGetsStoredAsString() { - JdbcPersistentEntity persistentEntity = new JdbcMappingContext(new DefaultNamingStrategy()) + JdbcPersistentEntity persistentEntity = new JdbcMappingContext() .getRequiredPersistentEntity(DummyEntity.class); persistentEntity.doWithProperties((PropertyHandler) p -> { diff --git a/src/test/java/org/springframework/data/jdbc/repository/SimpleJdbcRepositoryEventsUnitTests.java b/src/test/java/org/springframework/data/jdbc/repository/SimpleJdbcRepositoryEventsUnitTests.java index 5688894c87..ef6b08798f 100644 --- a/src/test/java/org/springframework/data/jdbc/repository/SimpleJdbcRepositoryEventsUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/repository/SimpleJdbcRepositoryEventsUnitTests.java @@ -27,7 +27,6 @@ import org.springframework.data.jdbc.mapping.event.BeforeSave; import org.springframework.data.jdbc.mapping.event.Identifier; import org.springframework.data.jdbc.mapping.event.JdbcEvent; -import org.springframework.data.jdbc.mapping.model.DefaultNamingStrategy; import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory; import org.springframework.data.repository.CrudRepository; @@ -47,7 +46,7 @@ public class SimpleJdbcRepositoryEventsUnitTests { @Before public void before() { - final JdbcMappingContext context = new JdbcMappingContext(new DefaultNamingStrategy()); + final JdbcMappingContext context = new JdbcMappingContext(); JdbcRepositoryFactory factory = new JdbcRepositoryFactory( // publisher, // context, // diff --git a/src/test/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBeanUnitTests.java b/src/test/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBeanUnitTests.java index 513d9231d7..de2c85563d 100644 --- a/src/test/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBeanUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBeanUnitTests.java @@ -4,6 +4,7 @@ import static org.mockito.Mockito.*; import static org.springframework.test.util.ReflectionTestUtils.*; +import java.time.Duration; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -17,11 +18,15 @@ import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationEventPublisher; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.converter.Converter; import org.springframework.data.annotation.Id; import org.springframework.data.jdbc.core.CascadingDataAccessStrategy; import org.springframework.data.jdbc.core.DataAccessStrategy; import org.springframework.data.jdbc.core.DefaultDataAccessStrategy; import org.springframework.data.jdbc.core.DelegatingDataAccessStrategy; +import org.springframework.data.jdbc.mapping.model.ConversionCustomizer; +import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; import org.springframework.data.jdbc.mybatis.MyBatisDataAccessStrategy; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.core.support.RepositoryFactorySupport; @@ -29,6 +34,7 @@ import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; +import org.springframework.lang.Nullable; import org.springframework.util.ReflectionUtils; /** @@ -43,6 +49,7 @@ public class JdbcRepositoryFactoryBeanUnitTests { static final String ACCESS_STRATEGY_FIELD_NAME_IN_FACTORY = "accessStrategy"; static final String OPERATIONS_FIELD_NAME_IN_DEFAULT_ACCESS_STRATEGY = "operations"; + private static final String MAPPING_CONTEXT_FIELD_NAME_IN_FACTORY = "context"; ApplicationEventPublisher eventPublisher = mock(ApplicationEventPublisher.class); ApplicationContext context = mock(ApplicationContext.class); @@ -52,12 +59,15 @@ public class JdbcRepositoryFactoryBeanUnitTests { Map namedJdbcOperations = new HashMap<>(); Map sqlSessionFactories = new HashMap<>(); + Map conversionCustomizers = new HashMap<>(); + { when(context.getBeansOfType(DataSource.class)).thenReturn(dataSources); when(context.getBeansOfType(JdbcOperations.class)).thenReturn(jdbcOperations); when(context.getBeansOfType(NamedParameterJdbcOperations.class)).thenReturn(namedJdbcOperations); when(context.getBeansOfType(SqlSessionFactory.class)).thenReturn(sqlSessionFactories); + when(context.getBeansOfType(ConversionCustomizer.class)).thenReturn(conversionCustomizers); } @Test // DATAJDBC-100 @@ -236,6 +246,33 @@ public Class loadClass(String name) throws ClassNotFoundException { ReflectionUtils.getAllDeclaredMethods(loadedClass); } + @Test // DATAJDBC-147 + public void registersConversionsCorrectly() { + + dataSources.put("anyname", mock(DataSource.class)); + conversionCustomizers.put("anyname", cs -> { + + cs.addConverter(new Converter() { + + @Nullable + @Override + public Long convert(Duration duration) { + return duration.toHours(); + } + }); + }); + + JdbcRepositoryFactoryBean factoryBean = // + new JdbcRepositoryFactoryBean<>(DummyEntityRepository.class, eventPublisher, context); + + RepositoryFactorySupport factory = factoryBean.doCreateRepositoryFactory(); + + JdbcMappingContext mappingContext = (JdbcMappingContext) getField(factory, MAPPING_CONTEXT_FIELD_NAME_IN_FACTORY); + ConversionService conversions = mappingContext.getConversions(); + + assertThat(conversions.convert(Duration.ofDays(3), Long.class)).isEqualTo(72L); + } + private Condition using(NamedParameterJdbcOperations expectedOperations) { Predicate predicate = r -> extractNamedParameterJdbcOperations(r) == expectedOperations; diff --git a/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java b/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java index 03f847a666..7193bd681d 100644 --- a/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java +++ b/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java @@ -50,12 +50,12 @@ public class TestConfiguration { @Bean JdbcRepositoryFactory jdbcRepositoryFactory() { - final JdbcMappingContext context = new JdbcMappingContext(new DefaultNamingStrategy(){ + final JdbcMappingContext context = new JdbcMappingContext(new DefaultNamingStrategy() { @Override public String getColumnName(JdbcPersistentProperty property) { return super.getColumnName(property); } - }); + }, __ -> {}); return new JdbcRepositoryFactory( // publisher, //