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