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 32a70734..6c1b0a3a 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.Optional; 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, @@ -222,14 +217,6 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy { 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(); @@ -295,7 +282,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy { } 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) { @@ -323,7 +310,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy { 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 00000000..c562cab2 --- /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 eda46bca..f5681129 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.Collections; 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 @@ public class JdbcMappingContext extends AbstractMappingContext((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 942efe12..cb717b33 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.DataAccessStrategy; 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 @@ public class JdbcRepositoryFactoryBean, S, ID extend 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 @@ public class JdbcRepositoryFactoryBean, S, ID extend 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/DefaultDataAccessStrategyUnitTests.java b/src/test/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategyUnitTests.java index 687386b6..c49003ee 100644 --- a/src/test/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategyUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategyUnitTests.java @@ -15,15 +15,12 @@ */ package org.springframework.data.jdbc.core; -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; - -import lombok.RequiredArgsConstructor; - import java.util.HashMap; +import lombok.RequiredArgsConstructor; import org.junit.Test; import org.mockito.ArgumentCaptor; + import org.springframework.data.annotation.Id; import org.springframework.data.jdbc.mapping.model.DefaultNamingStrategy; import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; @@ -31,6 +28,9 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.support.KeyHolder; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + /** * @author Jens Schauder */ @@ -39,7 +39,7 @@ public class DefaultDataAccessStrategyUnitTests { public static final long ID_FROM_ADDITIONAL_VALUES = 23L; public static final long ORIGINAL_ID = 4711L; - JdbcMappingContext context = new JdbcMappingContext(new DefaultNamingStrategy()); + JdbcMappingContext context = new JdbcMappingContext(new DefaultNamingStrategy(), __ -> {}); NamedParameterJdbcOperations jdbcOperations = mock(NamedParameterJdbcOperations.class); HashMap additionalParameters = new HashMap<>(); ArgumentCaptor captor = ArgumentCaptor.forClass(SqlParameterSource.class); diff --git a/src/test/java/org/springframework/data/jdbc/core/DefaultJdbcInterpreterUnitTests.java b/src/test/java/org/springframework/data/jdbc/core/DefaultJdbcInterpreterUnitTests.java index 832437f5..4cde85ee 100644 --- a/src/test/java/org/springframework/data/jdbc/core/DefaultJdbcInterpreterUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/core/DefaultJdbcInterpreterUnitTests.java @@ -15,14 +15,12 @@ */ package org.springframework.data.jdbc.core; -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; - import java.util.AbstractMap.SimpleEntry; import java.util.Map; import org.junit.Test; import org.mockito.ArgumentCaptor; + import org.springframework.data.annotation.Id; import org.springframework.data.jdbc.core.conversion.DbAction; import org.springframework.data.jdbc.core.conversion.DbAction.Insert; @@ -31,6 +29,9 @@ import org.springframework.data.jdbc.mapping.model.DefaultNamingStrategy; import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; import org.springframework.data.jdbc.mapping.model.JdbcPersistentProperty; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + /** * Unit tests for {@link DefaultJdbcInterpreter} * @@ -46,7 +47,7 @@ public class DefaultJdbcInterpreterUnitTests { public String getReverseColumnName(JdbcPersistentProperty property) { return BACK_REFERENCE; } - }); + }, __ -> {}); DataAccessStrategy dataAccessStrategy = mock(DataAccessStrategy.class); DefaultJdbcInterpreter interpreter = new DefaultJdbcInterpreter(context, dataAccessStrategy); 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 0385c15a..09201b53 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.DefaultConversionService; 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 class EntityRowMapperUnitTests { 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 fda03436..87f2bce0 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.Bean; 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 @@ public class JdbcEntityTemplateIntegrationTests { 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 36f05af1..96020cbb 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 @@ public class SqlGeneratorContextBasedNamingStrategyUnitTests { */ 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 733ad5be..12403a90 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 class SqlGeneratorFixedNamingStrategyUnitTests { */ 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 47f90538..68ae2216 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 4f66b36f..f84b23d8 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.mockito.junit.MockitoJUnitRunner; 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 @@ import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; @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 a59aec6b..093de9fc 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.AggregateChange.Kind; 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 @@ import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; 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 ce9bf881..377370d7 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 5688894c..ef6b0879 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.BeforeDelete; 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 513d9231..de2c8556 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.assertj.core.api.Assertions.*; 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.assertj.core.api.Condition; 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.instrument.classloading.ShadowingClassLoader; 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 JdbcRepositoryFactoryBeanUnitTests { 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 03f847a6..7193bd68 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, //