DATAJDBC-137 - Cleanups in the repository and repository.support packages.

This commit is contained in:
Oliver Gierke
2018-05-15 11:01:45 +02:00
parent fe98964d72
commit eab63d8848
15 changed files with 243 additions and 129 deletions

View File

@@ -100,7 +100,7 @@ public class CascadingDataAccessStrategy implements DataAccessStrategy {
}
private <T> T collect(Function<DataAccessStrategy, T> function) {
return strategies.stream().collect(new FunctionCollector<>(function));
return strategies.stream().collect(new FunctionCollector<T>(function));
}
private void collectVoid(Consumer<DataAccessStrategy> consumer) {

View File

@@ -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 <T> RowMapper<? extends T> rowMapperFor(Class<T> type) {
return null;
}

View File

@@ -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<T, ID> implements CrudRepository<T, ID> {
private final JdbcPersistentEntityInformation<T, ID> entityInformation;
private final JdbcEntityOperations entityOperations;
/**
* Creates a new {@link SimpleJdbcRepository}.
*/
public SimpleJdbcRepository(JdbcEntityTemplate entityOperations,
JdbcPersistentEntityInformation<T, ID> entityInformation) {
this.entityOperations = entityOperations;
this.entityInformation = entityInformation;
}
private final @NonNull JdbcEntityOperations entityOperations;
private final @NonNull JdbcPersistentEntityInformation<T, ID> entityInformation;
/*
* (non-Javadoc)
@@ -136,12 +129,9 @@ public class SimpleJdbcRepository<T, ID> implements CrudRepository<T, ID> {
* @see org.springframework.data.repository.CrudRepository#delete(java.lang.Iterable)
*/
@Override
@SuppressWarnings("unchecked")
public void deleteAll(Iterable<? extends T> entities) {
for (T entity : entities) {
entityOperations.delete(entity, (Class<T>) entity.getClass());
}
entities.forEach(it -> entityOperations.delete(it, (Class<T>) it.getClass()));
}
@Override

View File

@@ -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<>( //

View File

@@ -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 <T, ID> EntityInformation<T, ID> getEntityInformation(Class<T> aClass) {
return (EntityInformation<T, ID>) 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<QueryLookupStrategy> 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));
}
}

View File

@@ -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<T extends Repository<S, ID>, S, ID extends Serializable> //
@@ -47,14 +48,24 @@ public class JdbcRepositoryFactoryBean<T extends Repository<S, ID>, 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<? extends T> 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<T extends Repository<S, ID>, 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<T extends Repository<S, ID>, 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<T extends Repository<S, ID>, 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();

View File

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

View File

@@ -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<DbAction> actions = event.getChange().getActions();
List<DbAction<?>> 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<DbAction> actions = event.getChange().getActions();
List<DbAction<?>> actions = event.getChange().getActions();
actions.add(DbAction.insert(log, null, null));
};
}

View File

@@ -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<BeforeSaveEvent>) beforeInsert -> ((EntityWithColumnsRequiringConversions) beforeInsert
.getEntity()).setIdTimestamp(getNow());
}

View File

@@ -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() {

View File

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

View File

@@ -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<Object> {
@Override
public Object mapRow(ResultSet rs, int rowNum) {

View File

@@ -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<DummyEntityRepository, DummyEntity, Long> 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();

View File

@@ -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<Object> {
private static class CustomRowMapper implements RowMapper {
@Override
public Object mapRow(ResultSet rs, int rowNum) {
return null;

View File

@@ -59,10 +59,9 @@ public class TestConfiguration {
final JdbcMappingContext context = new JdbcMappingContext(NamingStrategy.INSTANCE, jdbcTemplate, __ -> {});
return new JdbcRepositoryFactory( //
publisher, //
dataAccessStrategy, //
context, //
dataAccessStrategy //
);
publisher);
}
@Bean