From eab63d8848182af44b4c5ddfa8dae0d2d06b7311 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 15 May 2018 11:01:45 +0200 Subject: [PATCH] DATAJDBC-137 - Cleanups in the repository and repository.support packages. --- .../core/CascadingDataAccessStrategy.java | 2 +- .../data/jdbc/repository/RowMapperMap.java | 4 ++ .../jdbc/repository/SimpleJdbcRepository.java | 28 +++------ .../support/JdbcQueryLookupStrategy.java | 24 ++++++-- .../support/JdbcRepositoryFactory.java | 54 ++++++++++++----- .../support/JdbcRepositoryFactoryBean.java | 26 ++++++-- .../support/JdbcRepositoryQuery.java | 48 +++++++++++---- ...ryManipulateDbActionsIntegrationTests.java | 15 +++-- ...oryPropertyConversionIntegrationTests.java | 3 +- .../SimpleJdbcRepositoryEventsUnitTests.java | 50 +++++++++++----- .../JdbcQueryLookupStrategyUnitTests.java | 31 +++++----- .../support/JdbcQueryMethodUnitTests.java | 10 +++- .../JdbcRepositoryFactoryBeanUnitTests.java | 12 +++- .../support/JdbcRepositoryQueryUnitTests.java | 60 ++++++++++--------- .../data/jdbc/testing/TestConfiguration.java | 5 +- 15 files changed, 243 insertions(+), 129 deletions(-) diff --git a/src/main/java/org/springframework/data/jdbc/core/CascadingDataAccessStrategy.java b/src/main/java/org/springframework/data/jdbc/core/CascadingDataAccessStrategy.java index 1f394aa3..0fd54169 100644 --- a/src/main/java/org/springframework/data/jdbc/core/CascadingDataAccessStrategy.java +++ b/src/main/java/org/springframework/data/jdbc/core/CascadingDataAccessStrategy.java @@ -100,7 +100,7 @@ public class CascadingDataAccessStrategy implements DataAccessStrategy { } private T collect(Function function) { - return strategies.stream().collect(new FunctionCollector<>(function)); + return strategies.stream().collect(new FunctionCollector(function)); } private void collectVoid(Consumer consumer) { diff --git a/src/main/java/org/springframework/data/jdbc/repository/RowMapperMap.java b/src/main/java/org/springframework/data/jdbc/repository/RowMapperMap.java index 1ef35d0d..2fd0d988 100644 --- a/src/main/java/org/springframework/data/jdbc/repository/RowMapperMap.java +++ b/src/main/java/org/springframework/data/jdbc/repository/RowMapperMap.java @@ -30,6 +30,10 @@ public interface RowMapperMap { */ RowMapperMap EMPTY = new RowMapperMap() { + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.repository.RowMapperMap#rowMapperFor(java.lang.Class) + */ public RowMapper rowMapperFor(Class type) { return null; } diff --git a/src/main/java/org/springframework/data/jdbc/repository/SimpleJdbcRepository.java b/src/main/java/org/springframework/data/jdbc/repository/SimpleJdbcRepository.java index b6eb7cb0..13cd83e2 100644 --- a/src/main/java/org/springframework/data/jdbc/repository/SimpleJdbcRepository.java +++ b/src/main/java/org/springframework/data/jdbc/repository/SimpleJdbcRepository.java @@ -15,34 +15,27 @@ */ package org.springframework.data.jdbc.repository; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + import java.util.ArrayList; import java.util.List; import java.util.Optional; import org.springframework.data.jdbc.core.JdbcEntityOperations; -import org.springframework.data.jdbc.core.JdbcEntityTemplate; import org.springframework.data.jdbc.mapping.model.JdbcPersistentEntityInformation; import org.springframework.data.repository.CrudRepository; /** * @author Jens Schauder + * @author Oliver Gierke * @since 1.0 */ +@RequiredArgsConstructor public class SimpleJdbcRepository implements CrudRepository { - private final JdbcPersistentEntityInformation entityInformation; - - private final JdbcEntityOperations entityOperations; - - /** - * Creates a new {@link SimpleJdbcRepository}. - */ - public SimpleJdbcRepository(JdbcEntityTemplate entityOperations, - JdbcPersistentEntityInformation entityInformation) { - - this.entityOperations = entityOperations; - this.entityInformation = entityInformation; - } + private final @NonNull JdbcEntityOperations entityOperations; + private final @NonNull JdbcPersistentEntityInformation entityInformation; /* * (non-Javadoc) @@ -136,12 +129,9 @@ public class SimpleJdbcRepository implements CrudRepository { * @see org.springframework.data.repository.CrudRepository#delete(java.lang.Iterable) */ @Override + @SuppressWarnings("unchecked") public void deleteAll(Iterable entities) { - - for (T entity : entities) { - entityOperations.delete(entity, (Class) entity.getClass()); - - } + entities.forEach(it -> entityOperations.delete(it, (Class) it.getClass())); } @Override diff --git a/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java b/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java index 5710b38c..f2121fe2 100644 --- a/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java +++ b/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java @@ -26,16 +26,17 @@ import org.springframework.data.projection.ProjectionFactory; import org.springframework.data.repository.core.NamedQueries; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.query.QueryLookupStrategy; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.SingleColumnRowMapper; +import org.springframework.util.Assert; /** * {@link QueryLookupStrategy} for JDBC repositories. Currently only supports annotated queries. * * @author Jens Schauder * @author Kazuki Shimizu + * @author Oliver Gierke * @since 1.0 */ class JdbcQueryLookupStrategy implements QueryLookupStrategy { @@ -45,8 +46,19 @@ class JdbcQueryLookupStrategy implements QueryLookupStrategy { private final RowMapperMap rowMapperMap; private final ConversionService conversionService; - JdbcQueryLookupStrategy(QueryMethodEvaluationContextProvider evaluationContextProvider, JdbcMappingContext context, - DataAccessStrategy accessStrategy, RowMapperMap rowMapperMap) { + /** + * Creates a new {@link JdbcQueryLookupStrategy} for the given {@link JdbcMappingContext}, {@link DataAccessStrategy} + * and {@link RowMapperMap}. + * + * @param context must not be {@literal null}. + * @param accessStrategy must not be {@literal null}. + * @param rowMapperMap must not be {@literal null}. + */ + JdbcQueryLookupStrategy(JdbcMappingContext context, DataAccessStrategy accessStrategy, RowMapperMap rowMapperMap) { + + Assert.notNull(context, "JdbcMappingContext must not be null!"); + Assert.notNull(accessStrategy, "DataAccessStrategy must not be null!"); + Assert.notNull(rowMapperMap, "RowMapperMap must not be null!"); this.context = context; this.accessStrategy = accessStrategy; @@ -54,6 +66,10 @@ class JdbcQueryLookupStrategy implements QueryLookupStrategy { this.conversionService = context.getConversions(); } + /* + * (non-Javadoc) + * @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.projection.ProjectionFactory, org.springframework.data.repository.core.NamedQueries) + */ @Override public RepositoryQuery resolveQuery(Method method, RepositoryMetadata repositoryMetadata, ProjectionFactory projectionFactory, NamedQueries namedQueries) { @@ -78,7 +94,7 @@ class JdbcQueryLookupStrategy implements QueryLookupStrategy { Class domainType = queryMethod.getReturnedObjectType(); - RowMapper typeMappedRowMapper = rowMapperMap.rowMapperFor(domainType); + RowMapper typeMappedRowMapper = rowMapperMap.rowMapperFor(domainType); return typeMappedRowMapper == null // ? new EntityRowMapper<>( // diff --git a/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactory.java b/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactory.java index 5ba361ce..3830c73b 100644 --- a/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactory.java +++ b/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactory.java @@ -45,38 +45,73 @@ public class JdbcRepositoryFactory extends RepositoryFactorySupport { private final JdbcMappingContext context; private final ApplicationEventPublisher publisher; private final DataAccessStrategy accessStrategy; + private RowMapperMap rowMapperMap = RowMapperMap.EMPTY; - public JdbcRepositoryFactory(ApplicationEventPublisher publisher, JdbcMappingContext context, - DataAccessStrategy dataAccessStrategy) { + /** + * Creates a new {@link JdbcRepositoryFactory} for the given {@link DataAccessStrategy}, {@link JdbcMappingContext} + * and {@link ApplicationEventPublisher}. + * + * @param dataAccessStrategy must not be {@literal null}. + * @param context must not be {@literal null}. + * @param publisher must not be {@literal null}. + */ + public JdbcRepositoryFactory(DataAccessStrategy dataAccessStrategy, JdbcMappingContext context, + ApplicationEventPublisher publisher) { + + Assert.notNull(dataAccessStrategy, "DataAccessStrategy must not be null!"); + Assert.notNull(context, "JdbcMappingContext must not be null!"); + Assert.notNull(publisher, "ApplicationEventPublisher must not be null!"); this.publisher = publisher; this.context = context; this.accessStrategy = dataAccessStrategy; } + /** + * @param rowMapperMap must not be {@literal null} consider {@link RowMapperMap#EMPTY} instead. + */ + public void setRowMapperMap(RowMapperMap rowMapperMap) { + + Assert.notNull(rowMapperMap, "RowMapperMap must not be null!"); + + this.rowMapperMap = rowMapperMap; + } + @SuppressWarnings("unchecked") @Override public EntityInformation getEntityInformation(Class aClass) { return (EntityInformation) context.getRequiredPersistentEntityInformation(aClass); } - @SuppressWarnings("unchecked") + /* + * (non-Javadoc) + * @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getTargetRepository(org.springframework.data.repository.core.RepositoryInformation) + */ @Override protected Object getTargetRepository(RepositoryInformation repositoryInformation) { - JdbcPersistentEntityInformation persistentEntityInformation = context + JdbcPersistentEntityInformation persistentEntityInformation = context .getRequiredPersistentEntityInformation(repositoryInformation.getDomainType()); + JdbcEntityTemplate template = new JdbcEntityTemplate(publisher, context, accessStrategy); return new SimpleJdbcRepository<>(template, persistentEntityInformation); } + /* + * (non-Javadoc) + * @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getRepositoryBaseClass(org.springframework.data.repository.core.RepositoryMetadata) + */ @Override protected Class getRepositoryBaseClass(RepositoryMetadata repositoryMetadata) { return SimpleJdbcRepository.class; } + /* + * (non-Javadoc) + * @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getQueryLookupStrategy(org.springframework.data.repository.query.QueryLookupStrategy.Key, org.springframework.data.repository.query.EvaluationContextProvider) + */ @Override protected Optional getQueryLookupStrategy(QueryLookupStrategy.Key key, QueryMethodEvaluationContextProvider evaluationContextProvider) { @@ -88,15 +123,6 @@ public class JdbcRepositoryFactory extends RepositoryFactorySupport { throw new IllegalArgumentException(String.format("Unsupported query lookup strategy %s!", key)); } - return Optional.of(new JdbcQueryLookupStrategy(evaluationContextProvider, context, accessStrategy, rowMapperMap)); - } - - /** - * @param rowMapperMap must not be {@literal null} consider {@link RowMapperMap#EMPTY} instead. - */ - public void setRowMapperMap(RowMapperMap rowMapperMap) { - - Assert.notNull(rowMapperMap, "RowMapperMap must not be null!"); - this.rowMapperMap = rowMapperMap; + return Optional.of(new JdbcQueryLookupStrategy(context, accessStrategy, rowMapperMap)); } } 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 e6ec1e1c..5eca80c9 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 @@ -37,6 +37,7 @@ import org.springframework.util.Assert; * @author Jens Schauder * @author Greg Turnquist * @author Christoph Strobl + * @author Oliver Gierke * @since 1.0 */ public class JdbcRepositoryFactoryBean, S, ID extends Serializable> // @@ -47,14 +48,24 @@ public class JdbcRepositoryFactoryBean, S, ID extend private DataAccessStrategy dataAccessStrategy; private RowMapperMap rowMapperMap = RowMapperMap.EMPTY; + /** + * Creates a new {@link JdbcRepositoryFactoryBean} for the given repository interface. + * + * @param repositoryInterface must not be {@literal null}. + */ JdbcRepositoryFactoryBean(Class repositoryInterface) { super(repositoryInterface); } + /* + * (non-Javadoc) + * @see org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport#setApplicationEventPublisher(org.springframework.context.ApplicationEventPublisher) + */ @Override public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { super.setApplicationEventPublisher(publisher); + this.publisher = publisher; } @@ -66,8 +77,8 @@ public class JdbcRepositoryFactoryBean, S, ID extend @Override protected RepositoryFactorySupport doCreateRepositoryFactory() { - JdbcRepositoryFactory jdbcRepositoryFactory = new JdbcRepositoryFactory(publisher, mappingContext, - dataAccessStrategy); + JdbcRepositoryFactory jdbcRepositoryFactory = new JdbcRepositoryFactory(dataAccessStrategy, mappingContext, + publisher); jdbcRepositoryFactory.setRowMapperMap(rowMapperMap); return jdbcRepositoryFactory; @@ -97,6 +108,10 @@ public class JdbcRepositoryFactoryBean, S, ID extend this.rowMapperMap = rowMapperMap; } + /* + * (non-Javadoc) + * @see org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport#afterPropertiesSet() + */ @Override public void afterPropertiesSet() { @@ -104,13 +119,12 @@ public class JdbcRepositoryFactoryBean, S, ID extend if (dataAccessStrategy == null) { - dataAccessStrategy = new DefaultDataAccessStrategy( // - new SqlGeneratorSource(mappingContext), // - mappingContext); + SqlGeneratorSource sqlGeneratorSource = new SqlGeneratorSource(mappingContext); + this.dataAccessStrategy = new DefaultDataAccessStrategy(sqlGeneratorSource, mappingContext); } if (rowMapperMap == null) { - rowMapperMap = RowMapperMap.EMPTY; + this.rowMapperMap = RowMapperMap.EMPTY; } super.afterPropertiesSet(); diff --git a/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryQuery.java b/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryQuery.java index 088d412f..c0d016a9 100644 --- a/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryQuery.java +++ b/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryQuery.java @@ -21,6 +21,7 @@ import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** @@ -29,6 +30,7 @@ import org.springframework.util.StringUtils; * * @author Jens Schauder * @author Kazuki Shimizu + * @author Oliver Gierke * @since 1.0 */ class JdbcRepositoryQuery implements RepositoryQuery { @@ -39,26 +41,36 @@ class JdbcRepositoryQuery implements RepositoryQuery { private final JdbcMappingContext context; private final RowMapper rowMapper; - JdbcRepositoryQuery(JdbcQueryMethod queryMethod, JdbcMappingContext context, RowMapper defaultRowMapper) { + /** + * Creates a new {@link JdbcRepositoryQuery} for the given {@link JdbcQueryMethod}, {@link JdbcMappingContext} and + * {@link RowMapper}. + * + * @param queryMethod must not be {@literal null}. + * @param context must not be {@literal null}. + * @param defaultRowMapper can be {@literal null} (only in case of a modifying query). + */ + JdbcRepositoryQuery(JdbcQueryMethod queryMethod, JdbcMappingContext context, RowMapper defaultRowMapper) { + + Assert.notNull(queryMethod, "Query method must not be null!"); + Assert.notNull(context, "JdbcMappingContext must not be null!"); + + if (!queryMethod.isModifyingQuery()) { + Assert.notNull(defaultRowMapper, "RowMapper must not be null!"); + } this.queryMethod = queryMethod; this.context = context; this.rowMapper = createRowMapper(queryMethod, defaultRowMapper); } - private static RowMapper createRowMapper(JdbcQueryMethod queryMethod, RowMapper defaultRowMapper) { - - Class rowMapperClass = queryMethod.getRowMapperClass(); - - return rowMapperClass == null || rowMapperClass == RowMapper.class ? defaultRowMapper - : (RowMapper) BeanUtils.instantiateClass(rowMapperClass); - } - + /* + * (non-Javadoc) + * @see org.springframework.data.repository.query.RepositoryQuery#execute(java.lang.Object[]) + */ @Override public Object execute(Object[] objects) { String query = determineQuery(); - MapSqlParameterSource parameters = bindParameters(objects); if (queryMethod.isModifyingQuery()) { @@ -80,6 +92,10 @@ class JdbcRepositoryQuery implements RepositoryQuery { } } + /* + * (non-Javadoc) + * @see org.springframework.data.repository.query.RepositoryQuery#getQueryMethod() + */ @Override public JdbcQueryMethod getQueryMethod() { return queryMethod; @@ -92,17 +108,29 @@ class JdbcRepositoryQuery implements RepositoryQuery { if (StringUtils.isEmpty(query)) { throw new IllegalStateException(String.format("No query specified on %s", queryMethod.getName())); } + return query; } private MapSqlParameterSource bindParameters(Object[] objects) { MapSqlParameterSource parameters = new MapSqlParameterSource(); + queryMethod.getParameters().getBindableParameters().forEach(p -> { String parameterName = p.getName().orElseThrow(() -> new IllegalStateException(PARAMETER_NEEDS_TO_BE_NAMED)); parameters.addValue(parameterName, objects[p.getIndex()]); }); + return parameters; } + + private static RowMapper createRowMapper(JdbcQueryMethod queryMethod, RowMapper defaultRowMapper) { + + Class rowMapperClass = queryMethod.getRowMapperClass(); + + return rowMapperClass == null || rowMapperClass == RowMapper.class // + ? defaultRowMapper // + : (RowMapper) BeanUtils.instantiateClass(rowMapperClass); + } } diff --git a/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryManipulateDbActionsIntegrationTests.java b/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryManipulateDbActionsIntegrationTests.java index 2ca4c0a0..3bc888cb 100644 --- a/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryManipulateDbActionsIntegrationTests.java +++ b/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryManipulateDbActionsIntegrationTests.java @@ -15,8 +15,8 @@ */ package org.springframework.data.jdbc.repository; -import static java.util.Arrays.asList; -import static org.assertj.core.api.Assertions.assertThat; +import static java.util.Arrays.*; +import static org.assertj.core.api.Assertions.*; import junit.framework.AssertionFailedError; import lombok.Data; @@ -80,7 +80,7 @@ public class JdbcRepositoryManipulateDbActionsIntegrationTests { entity.id, // entity.name, // true) // - ); + ); } @@ -103,14 +103,14 @@ public class JdbcRepositoryManipulateDbActionsIntegrationTests { one.id, // one.name, // true) // - ); + ); assertThat(repository.findById(two.id)) // .contains(new DummyEntity( // two.id, // two.name, // true) // - ); + ); } @Test // DATAJDBC-120 @@ -203,7 +203,7 @@ public class JdbcRepositoryManipulateDbActionsIntegrationTests { DummyEntity entity = (DummyEntity) event.getOptionalEntity().orElseThrow(AssertionFailedError::new); entity.deleted = true; - List actions = event.getChange().getActions(); + List> actions = event.getChange().getActions(); actions.clear(); actions.add(DbAction.update(entity, null, null)); }; @@ -222,8 +222,7 @@ public class JdbcRepositoryManipulateDbActionsIntegrationTests { log.entity = entity; log.text = entity.name + " saved"; - - List actions = event.getChange().getActions(); + List> actions = event.getChange().getActions(); actions.add(DbAction.insert(log, null, null)); }; } diff --git a/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryPropertyConversionIntegrationTests.java b/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryPropertyConversionIntegrationTests.java index 6ecf3cc2..cf09a7b4 100644 --- a/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryPropertyConversionIntegrationTests.java +++ b/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryPropertyConversionIntegrationTests.java @@ -33,7 +33,6 @@ import org.assertj.core.api.SoftAssertions; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Bean; @@ -76,7 +75,7 @@ public class JdbcRepositoryPropertyConversionIntegrationTests { } @Bean - ApplicationListener applicationListener() { + ApplicationListener applicationListener() { return (ApplicationListener) beforeInsert -> ((EntityWithColumnsRequiringConversions) beforeInsert .getEntity()).setIdTimestamp(getNow()); } 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 b901799d..49ecfdc1 100644 --- a/src/test/java/org/springframework/data/jdbc/repository/SimpleJdbcRepositoryEventsUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/repository/SimpleJdbcRepositoryEventsUnitTests.java @@ -1,10 +1,23 @@ +/* + * Copyright 2017-2018 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.repository; import static java.util.Arrays.*; import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import junit.framework.AssertionFailedError; @@ -42,6 +55,7 @@ import org.springframework.jdbc.support.KeyHolder; * * @author Jens Schauder * @author Mark Paluch + * @author Oliver Gierke */ public class SimpleJdbcRepositoryEventsUnitTests { @@ -61,15 +75,15 @@ public class SimpleJdbcRepositoryEventsUnitTests { )); JdbcRepositoryFactory factory = new JdbcRepositoryFactory( // - publisher, // + dataAccessStrategy, // context, // - dataAccessStrategy // - ); + publisher); repository = factory.getRepository(DummyEntityRepository.class); } @Test // DATAJDBC-99 + @SuppressWarnings("rawtypes") public void publishesEventsOnSave() { DummyEntity entity = new DummyEntity(23L); @@ -81,10 +95,11 @@ public class SimpleJdbcRepositoryEventsUnitTests { .containsExactly( // BeforeSaveEvent.class, // AfterSaveEvent.class // - ); + ); } @Test // DATAJDBC-99 + @SuppressWarnings("rawtypes") public void publishesEventsOnSaveMany() { DummyEntity entity1 = new DummyEntity(null); @@ -99,7 +114,7 @@ public class SimpleJdbcRepositoryEventsUnitTests { AfterSaveEvent.class, // BeforeSaveEvent.class, // AfterSaveEvent.class // - ); + ); } @Test // DATAJDBC-99 @@ -120,6 +135,7 @@ public class SimpleJdbcRepositoryEventsUnitTests { } @Test // DATAJDBC-99 + @SuppressWarnings("rawtypes") public void publishesEventsOnDeleteById() { repository.deleteById(23L); @@ -129,16 +145,17 @@ public class SimpleJdbcRepositoryEventsUnitTests { .containsExactly( // BeforeDeleteEvent.class, // AfterDeleteEvent.class // - ); + ); } @Test // DATAJDBC-197 + @SuppressWarnings("rawtypes") public void publishesEventsOnFindAll() { DummyEntity entity1 = new DummyEntity(42L); DummyEntity entity2 = new DummyEntity(23L); - doReturn(asList(entity1, entity2)).when(dataAccessStrategy).findAll(any(Class.class)); + doReturn(asList(entity1, entity2)).when(dataAccessStrategy).findAll(any()); repository.findAll(); @@ -147,16 +164,17 @@ public class SimpleJdbcRepositoryEventsUnitTests { .containsExactly( // AfterLoadEvent.class, // AfterLoadEvent.class // - ); + ); } @Test // DATAJDBC-197 + @SuppressWarnings("rawtypes") public void publishesEventsOnFindAllById() { DummyEntity entity1 = new DummyEntity(42L); DummyEntity entity2 = new DummyEntity(23L); - doReturn(asList(entity1, entity2)).when(dataAccessStrategy).findAllById(any(Iterable.class), any(Class.class)); + doReturn(asList(entity1, entity2)).when(dataAccessStrategy).findAllById(any(), any()); repository.findAllById(asList(42L, 23L)); @@ -165,14 +183,16 @@ public class SimpleJdbcRepositoryEventsUnitTests { .containsExactly( // AfterLoadEvent.class, // AfterLoadEvent.class // - ); + ); } @Test // DATAJDBC-197 + @SuppressWarnings("rawtypes") public void publishesEventsOnFindById() { DummyEntity entity1 = new DummyEntity(23L); - doReturn(entity1).when(dataAccessStrategy).findById(eq(23L), any(Class.class)); + + doReturn(entity1).when(dataAccessStrategy).findById(eq(23L), any()); repository.findById(23L); @@ -180,7 +200,7 @@ public class SimpleJdbcRepositoryEventsUnitTests { .extracting(e -> (Class) e.getClass()) // .containsExactly( // AfterLoadEvent.class // - ); + ); } private static NamedParameterJdbcOperations createIdGeneratingOperations() { diff --git a/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategyUnitTests.java b/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategyUnitTests.java index 3c66dba6..9eeb0d6e 100644 --- a/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategyUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategyUnitTests.java @@ -31,7 +31,6 @@ import org.springframework.data.jdbc.repository.query.Query; import org.springframework.data.projection.ProjectionFactory; import org.springframework.data.repository.core.NamedQueries; import org.springframework.data.repository.core.RepositoryMetadata; -import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.SqlParameterSource; @@ -40,10 +39,10 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource; * Unit tests for {@link JdbcQueryLookupStrategy}. * * @author Jens Schauder + * @author Oliver Gierke */ public class JdbcQueryLookupStrategyUnitTests { - QueryMethodEvaluationContextProvider evaluationContextProvider = mock(QueryMethodEvaluationContextProvider.class); JdbcMappingContext mappingContext = mock(JdbcMappingContext.class, RETURNS_DEEP_STUBS); DataAccessStrategy accessStrategy = mock(DataAccessStrategy.class); ProjectionFactory projectionFactory = mock(ProjectionFactory.class); @@ -53,24 +52,17 @@ public class JdbcQueryLookupStrategyUnitTests { @Before public void setup() { - metadata = mock(RepositoryMetadata.class); - when(metadata.getReturnedDomainClass(any(Method.class))).thenReturn((Class) NumberFormat.class); + this.metadata = mock(RepositoryMetadata.class); - } + doReturn(NumberFormat.class).when(metadata).getReturnedDomainClass(any(Method.class)); - private Method getMethod(String name) { - - try { - return this.getClass().getDeclaredMethod(name); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } } @Test // DATAJDBC-166 + @SuppressWarnings("unchecked") public void typeBasedRowMapperGetsUsedForQuery() { - RowMapper numberFormatMapper = mock(RowMapper.class); + RowMapper numberFormatMapper = mock(RowMapper.class); RowMapperMap rowMapperMap = new ConfigurableRowMapperMap().register(NumberFormat.class, numberFormatMapper); RepositoryQuery repositoryQuery = getRepositoryQuery("returningNumberFormat", rowMapperMap); @@ -83,8 +75,8 @@ public class JdbcQueryLookupStrategyUnitTests { private RepositoryQuery getRepositoryQuery(String name, RowMapperMap rowMapperMap) { - JdbcQueryLookupStrategy queryLookupStrategy = new JdbcQueryLookupStrategy(evaluationContextProvider, mappingContext, - accessStrategy, rowMapperMap); + JdbcQueryLookupStrategy queryLookupStrategy = new JdbcQueryLookupStrategy(mappingContext, accessStrategy, + rowMapperMap); return queryLookupStrategy.resolveQuery(getMethod(name), metadata, projectionFactory, namedQueries); } @@ -95,4 +87,13 @@ public class JdbcQueryLookupStrategyUnitTests { return null; } + private static Method getMethod(String name) { + + try { + return JdbcQueryLookupStrategyUnitTests.class.getDeclaredMethod(name); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + } diff --git a/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryMethodUnitTests.java b/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryMethodUnitTests.java index c450740b..0b5f1ece 100644 --- a/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryMethodUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryMethodUnitTests.java @@ -16,6 +16,7 @@ package org.springframework.data.jdbc.repository.support; import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.lang.reflect.Method; @@ -31,6 +32,7 @@ import org.springframework.jdbc.core.RowMapper; * Unit tests for {@link JdbcQueryMethod}. * * @author Jens Schauder + * @author Oliver Gierke */ public class JdbcQueryMethodUnitTests { @@ -40,7 +42,8 @@ public class JdbcQueryMethodUnitTests { public void returnsSqlStatement() throws NoSuchMethodException { RepositoryMetadata metadata = mock(RepositoryMetadata.class); - when(metadata.getReturnedDomainClass(any(Method.class))).thenReturn((Class) String.class); + + doReturn(String.class).when(metadata).getReturnedDomainClass(any(Method.class)); JdbcQueryMethod queryMethod = new JdbcQueryMethod(JdbcQueryMethodUnitTests.class.getDeclaredMethod("queryMethod"), metadata, mock(ProjectionFactory.class)); @@ -52,7 +55,8 @@ public class JdbcQueryMethodUnitTests { public void returnsSpecifiedRowMapperClass() throws NoSuchMethodException { RepositoryMetadata metadata = mock(RepositoryMetadata.class); - when(metadata.getReturnedDomainClass(any(Method.class))).thenReturn((Class) String.class); + + doReturn(String.class).when(metadata).getReturnedDomainClass(any(Method.class)); JdbcQueryMethod queryMethod = new JdbcQueryMethod(JdbcQueryMethodUnitTests.class.getDeclaredMethod("queryMethod"), metadata, mock(ProjectionFactory.class)); @@ -63,7 +67,7 @@ public class JdbcQueryMethodUnitTests { @Query(value = DUMMY_SELECT, rowMapperClass = CustomRowMapper.class) private void queryMethod() {} - private class CustomRowMapper implements RowMapper { + private class CustomRowMapper implements RowMapper { @Override public Object mapRow(ResultSet rs, int rowNum) { 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 41f0ff9a..6ae5acb3 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 @@ -24,12 +24,14 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.beans.factory.BeanFactory; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.annotation.Id; import org.springframework.data.jdbc.core.DataAccessStrategy; import org.springframework.data.jdbc.core.DefaultDataAccessStrategy; import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; import org.springframework.data.jdbc.repository.RowMapperMap; import org.springframework.data.repository.CrudRepository; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; import org.springframework.test.util.ReflectionTestUtils; /** @@ -38,6 +40,7 @@ import org.springframework.test.util.ReflectionTestUtils; * @author Jens Schauder * @author Greg Turnquist * @author Christoph Strobl + * @author Oliver Gierke */ @RunWith(MockitoJUnitRunner.class) public class JdbcRepositoryFactoryBeanUnitTests { @@ -45,11 +48,15 @@ public class JdbcRepositoryFactoryBeanUnitTests { JdbcRepositoryFactoryBean factoryBean; @Mock DataAccessStrategy dataAccessStrategy; - @Mock JdbcMappingContext mappingContext; + @Mock ApplicationEventPublisher publisher; + + JdbcMappingContext mappingContext; @Before public void setUp() { + this.mappingContext = new JdbcMappingContext(mock(NamedParameterJdbcOperations.class)); + // Setup standard configuration factoryBean = new JdbcRepositoryFactoryBean<>(DummyEntityRepository.class); } @@ -59,6 +66,7 @@ public class JdbcRepositoryFactoryBeanUnitTests { factoryBean.setDataAccessStrategy(dataAccessStrategy); factoryBean.setMappingContext(mappingContext); + factoryBean.setApplicationEventPublisher(publisher); factoryBean.afterPropertiesSet(); assertThat(factoryBean.getObject()).isNotNull(); @@ -74,6 +82,7 @@ public class JdbcRepositoryFactoryBeanUnitTests { public void afterPropertiesThowsExceptionWhenNoMappingContextSet() { factoryBean.setMappingContext(null); + factoryBean.setApplicationEventPublisher(publisher); factoryBean.afterPropertiesSet(); } @@ -81,6 +90,7 @@ public class JdbcRepositoryFactoryBeanUnitTests { public void afterPropertiesSetDefaultsNullablePropertiesCorrectly() { factoryBean.setMappingContext(mappingContext); + factoryBean.setApplicationEventPublisher(publisher); factoryBean.afterPropertiesSet(); assertThat(factoryBean.getObject()).isNotNull(); diff --git a/src/test/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryQueryUnitTests.java b/src/test/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryQueryUnitTests.java index 2d93d432..02e33e4b 100644 --- a/src/test/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryQueryUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryQueryUnitTests.java @@ -15,6 +15,11 @@ */ package org.springframework.data.jdbc.repository.support; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.sql.ResultSet; + import org.assertj.core.api.Assertions; import org.junit.Before; import org.junit.Test; @@ -24,51 +29,50 @@ import org.springframework.data.repository.query.Parameters; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.SqlParameterSource; -import java.sql.ResultSet; - -import static org.mockito.Mockito.*; - /** * Unit tests for {@link JdbcRepositoryQuery}. * * @author Jens Schauder + * @author Oliver Gierke */ public class JdbcRepositoryQueryUnitTests { JdbcQueryMethod queryMethod; JdbcMappingContext context; - RowMapper defaultRowMapper; + RowMapper defaultRowMapper; JdbcRepositoryQuery query; @Before public void setup() throws NoSuchMethodException { - Parameters parameters = new DefaultParameters(JdbcRepositoryQueryUnitTests.class.getDeclaredMethod("dummyMethod")); - queryMethod = mock(JdbcQueryMethod.class); - when(queryMethod.getParameters()).thenReturn(parameters); + this.queryMethod = mock(JdbcQueryMethod.class); - context = mock(JdbcMappingContext.class, RETURNS_DEEP_STUBS); - defaultRowMapper = mock(RowMapper.class); + Parameters parameters = new DefaultParameters( + JdbcRepositoryQueryUnitTests.class.getDeclaredMethod("dummyMethod")); + doReturn(parameters).when(queryMethod).getParameters(); + + this.context = mock(JdbcMappingContext.class, RETURNS_DEEP_STUBS); + this.defaultRowMapper = mock(RowMapper.class); + + this.query = new JdbcRepositoryQuery(queryMethod, context, defaultRowMapper); } @Test // DATAJDBC-165 public void emptyQueryThrowsException() { - when(queryMethod.getAnnotatedQuery()).thenReturn(null); - query = new JdbcRepositoryQuery(queryMethod, context, defaultRowMapper); + doReturn(null).when(queryMethod).getAnnotatedQuery(); Assertions.assertThatExceptionOfType(IllegalStateException.class) // - .isThrownBy(() -> query.execute(new Object[]{})); + .isThrownBy(() -> query.execute(new Object[] {})); } @Test // DATAJDBC-165 public void defaultRowMapperIsUsedByDefault() { - when(queryMethod.getAnnotatedQuery()).thenReturn("some sql statement"); - when(queryMethod.getRowMapperClass()).thenReturn((Class) RowMapper.class); - query = new JdbcRepositoryQuery(queryMethod, context, defaultRowMapper); + doReturn("some sql statement").when(queryMethod).getAnnotatedQuery(); + doReturn(RowMapper.class).when(queryMethod).getRowMapperClass(); - query.execute(new Object[]{}); + query.execute(new Object[] {}); verify(context.getTemplate()).queryForObject(anyString(), any(SqlParameterSource.class), eq(defaultRowMapper)); } @@ -76,10 +80,9 @@ public class JdbcRepositoryQueryUnitTests { @Test // DATAJDBC-165 public void defaultRowMapperIsUsedForNull() { - when(queryMethod.getAnnotatedQuery()).thenReturn("some sql statement"); - query = new JdbcRepositoryQuery(queryMethod, context, defaultRowMapper); + doReturn("some sql statement").when(queryMethod).getAnnotatedQuery(); - query.execute(new Object[]{}); + query.execute(new Object[] {}); verify(context.getTemplate()).queryForObject(anyString(), any(SqlParameterSource.class), eq(defaultRowMapper)); } @@ -87,22 +90,23 @@ public class JdbcRepositoryQueryUnitTests { @Test // DATAJDBC-165 public void customRowMapperIsUsedWhenSpecified() { - when(queryMethod.getAnnotatedQuery()).thenReturn("some sql statement"); - when(queryMethod.getRowMapperClass()).thenReturn((Class) CustomRowMapper.class); - query = new JdbcRepositoryQuery(queryMethod, context, defaultRowMapper); + doReturn("some sql statement").when(queryMethod).getAnnotatedQuery(); + doReturn(CustomRowMapper.class).when(queryMethod).getRowMapperClass(); - query.execute(new Object[]{}); + new JdbcRepositoryQuery(queryMethod, context, defaultRowMapper).execute(new Object[] {}); - verify(context.getTemplate()).queryForObject(anyString(), any(SqlParameterSource.class), isA(CustomRowMapper.class)); + verify(context.getTemplate()) // + .queryForObject(anyString(), any(SqlParameterSource.class), isA(CustomRowMapper.class)); } /** * The whole purpose of this method is to easily generate a {@link DefaultParameters} instance during test setup. */ - private void dummyMethod() { - } + @SuppressWarnings("unused") + private void dummyMethod() {} + + private static class CustomRowMapper implements RowMapper { - private static class CustomRowMapper implements RowMapper { @Override public Object mapRow(ResultSet rs, int rowNum) { return null; 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 1be321f9..fdeee16c 100644 --- a/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java +++ b/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java @@ -59,10 +59,9 @@ public class TestConfiguration { final JdbcMappingContext context = new JdbcMappingContext(NamingStrategy.INSTANCE, jdbcTemplate, __ -> {}); return new JdbcRepositoryFactory( // - publisher, // + dataAccessStrategy, // context, // - dataAccessStrategy // - ); + publisher); } @Bean