DATAJDBC-290 - Polishing.

Naming, formatting, and code structure improved.

Original pull request: #101.
This commit is contained in:
Jens Schauder
2018-12-03 17:21:31 +01:00
parent 4e7a109393
commit 3769db7a27
18 changed files with 313 additions and 276 deletions

View File

@@ -1,24 +1,28 @@
package org.springframework.data.jdbc.repository;
import org.springframework.data.jdbc.support.RowMapperResultsetExtractorEither;
import org.springframework.data.jdbc.support.RowMapperOrResultsetExtractor;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.lang.Nullable;
/**
* A map from a type to a {@link ResultSetExtractor} to be used for extracting that type from {@link java.sql.ResultSet}s.
* Configures a {@link org.springframework.jdbc.core.RowMapper} or a {@link ResultSetExtractor} for each type to be used
* for extracting entities of that type from a {@link java.sql.ResultSet}.
*
* @author Jens Schauder
* @author Evgeni Dimitrov
*/
public interface QueryMappingConfiguration {
<T> RowMapperResultsetExtractorEither<?> getMapper(Class<T> type);
@Nullable
<T> RowMapperOrResultsetExtractor<?> getMapperOrExtractor(Class<T> type);
/**
* An immutable empty instance that will return {@literal null} for all arguments.
*/
QueryMappingConfiguration EMPTY = new QueryMappingConfiguration() {
@Override
public <T> RowMapperResultsetExtractorEither<?> getMapper(Class<T> type) {
public <T> RowMapperOrResultsetExtractor<?> getMapperOrExtractor(Class<T> type) {
return null;
}

View File

@@ -4,28 +4,33 @@ import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
import org.springframework.data.jdbc.support.RowMapperResultsetExtractorEither;
import org.springframework.data.jdbc.support.RowMapperOrResultsetExtractor;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* A {@link QueryMappingConfiguration} that allows for registration of {@link RowMapper}s and {@link ResultSetExtractor}s via a fluent Api.
* A {@link QueryMappingConfiguration} that allows for registration of {@link RowMapper}s and
* {@link ResultSetExtractor}s via a fluent Api.
*
* @author Jens Schauder
* @author Evgeni Dimitrov
*/
public class DefaultQueryMappingConfiguration implements QueryMappingConfiguration{
private Map<Class<?>, RowMapperResultsetExtractorEither<?>> mappers = new LinkedHashMap<>();
public class DefaultQueryMappingConfiguration implements QueryMappingConfiguration {
private Map<Class<?>, RowMapperOrResultsetExtractor<?>> mappers = new LinkedHashMap<>();
@Nullable
public <T> RowMapperOrResultsetExtractor<?> getMapperOrExtractor(Class<T> type) {
public <T> RowMapperResultsetExtractorEither<?> getMapper(Class<T> type) {
Assert.notNull(type, "Type must not be null");
RowMapperResultsetExtractorEither<?> candidate = mappers.get(type);
RowMapperOrResultsetExtractor<?> candidate = mappers.get(type);
if (candidate == null) {
for (Map.Entry<Class<?>, RowMapperResultsetExtractorEither<?>> entry : mappers.entrySet()) {
for (Map.Entry<Class<?>, RowMapperOrResultsetExtractor<?>> entry : mappers.entrySet()) {
if (type.isAssignableFrom(entry.getKey())) {
candidate = entry.getValue();
@@ -41,17 +46,22 @@ public class DefaultQueryMappingConfiguration implements QueryMappingConfigurati
* @return this instance, so this can be used as a fluent interface.
*/
public <T> DefaultQueryMappingConfiguration registerRowMapper(Class<T> type, RowMapper<? extends T> rowMapper) {
mappers.put(type, RowMapperResultsetExtractorEither.of(rowMapper));
mappers.put(type, RowMapperOrResultsetExtractor.of(rowMapper));
return this;
}
/**
* Registers a the given {@link ResultSetExtractor} as to be used for the given type.
*
* @return this instance, so this can be used as a fluent interface.
*/
public <T> DefaultQueryMappingConfiguration registerResultSetExtractor(Class<T> type, ResultSetExtractor resultSetExtractor) {
mappers.put(type, RowMapperResultsetExtractorEither.of(resultSetExtractor));
public <T> DefaultQueryMappingConfiguration registerResultSetExtractor(Class<T> type,
ResultSetExtractor resultSetExtractor) {
mappers.put(type, RowMapperOrResultsetExtractor.of(resultSetExtractor));
return this;
}
}

View File

@@ -44,14 +44,14 @@ public @interface Query {
String value();
/**
* Optional {@link RowMapper} to use to convert the result of the query to domain class instances.
* Cannot be used along with {@link #resultSetExtractorClass()} only one of the two can be set.
* Optional {@link RowMapper} to use to convert the result of the query to domain class instances. Cannot be used
* along with {@link #resultSetExtractorClass()} only one of the two can be set.
*/
Class<? extends RowMapper> rowMapperClass() default RowMapper.class;
/**
* Optional {@link ResultSetExtractor} to use to convert the result of the query to domain class instances.
* Cannot be used along with {@link #rowMapperClass()} only one of the two can be set.
* Optional {@link ResultSetExtractor} to use to convert the result of the query to domain class instances. Cannot be
* used along with {@link #rowMapperClass()} only one of the two can be set.
*/
Class<? extends ResultSetExtractor> resultSetExtractorClass() default ResultSetExtractor.class;
}

View File

@@ -1,19 +0,0 @@
package org.springframework.data.jdbc.repository.support;
import org.springframework.data.jdbc.repository.query.Query;
/**
* Exception thrown when both {@link Query#resultSetExtractorClass()} and {@link Query#rowMapperClass()} are used in one {@link Query}.
*
* @author Evgeni Dimitrov
*/
public class InvalidQueryConfiguration extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 6604189906427682546L;
public InvalidQueryConfiguration(String message) {
super(message);
}
}

View File

@@ -21,7 +21,7 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.jdbc.core.DataAccessStrategy;
import org.springframework.data.jdbc.core.EntityRowMapper;
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
import org.springframework.data.jdbc.support.RowMapperResultsetExtractorEither;
import org.springframework.data.jdbc.support.RowMapperOrResultsetExtractor;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.relational.core.conversion.RelationalConverter;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
@@ -30,8 +30,6 @@ 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.RepositoryQuery;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SingleColumnRowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.util.Assert;
@@ -51,7 +49,7 @@ class JdbcQueryLookupStrategy implements QueryLookupStrategy {
private final RelationalMappingContext context;
private final RelationalConverter converter;
private final DataAccessStrategy accessStrategy;
private final QueryMappingConfiguration mapperMap;
private final QueryMappingConfiguration queryMappingConfiguration;
private final NamedParameterJdbcOperations operations;
/**
@@ -62,22 +60,23 @@ class JdbcQueryLookupStrategy implements QueryLookupStrategy {
* @param context must not be {@literal null}.
* @param converter must not be {@literal null}.
* @param accessStrategy must not be {@literal null}.
* @param rowMapperMap must not be {@literal null}.
* @param queryMappingConfiguration must not be {@literal null}.
*/
JdbcQueryLookupStrategy(ApplicationEventPublisher publisher, RelationalMappingContext context, RelationalConverter converter,
DataAccessStrategy accessStrategy, QueryMappingConfiguration rowMapperMap, NamedParameterJdbcOperations operations) {
JdbcQueryLookupStrategy(ApplicationEventPublisher publisher, RelationalMappingContext context,
RelationalConverter converter, DataAccessStrategy accessStrategy,
QueryMappingConfiguration queryMappingConfiguration, NamedParameterJdbcOperations operations) {
Assert.notNull(publisher, "Publisher must not be null!");
Assert.notNull(context, "RelationalMappingContext must not be null!");
Assert.notNull(converter, "RelationalConverter must not be null!");
Assert.notNull(accessStrategy, "DataAccessStrategy must not be null!");
Assert.notNull(rowMapperMap, "RowMapperMap must not be null!");
Assert.notNull(queryMappingConfiguration, "RowMapperMap must not be null!");
this.publisher = publisher;
this.context = context;
this.converter = converter;
this.accessStrategy = accessStrategy;
this.mapperMap = rowMapperMap;
this.queryMappingConfiguration = queryMappingConfiguration;
this.operations = operations;
}
@@ -91,35 +90,39 @@ class JdbcQueryLookupStrategy implements QueryLookupStrategy {
JdbcQueryMethod queryMethod = new JdbcQueryMethod(method, repositoryMetadata, projectionFactory);
RowMapperResultsetExtractorEither<?> mapper = queryMethod.isModifyingQuery() ? null : createMapper(queryMethod);
RowMapperOrResultsetExtractor<?> mapper = queryMethod.isModifyingQuery() ? null : createMapper(queryMethod);
return new JdbcRepositoryQuery(publisher, context, queryMethod, operations, mapper);
}
private RowMapperResultsetExtractorEither<?> createMapper(JdbcQueryMethod queryMethod) {
private RowMapperOrResultsetExtractor<?> createMapper(JdbcQueryMethod queryMethod) {
Class<?> returnedObjectType = queryMethod.getReturnedObjectType();
RelationalPersistentEntity<?> persistentEntity = context.getPersistentEntity(returnedObjectType);
if (persistentEntity == null) {
return RowMapperResultsetExtractorEither.of(
SingleColumnRowMapper.newInstance(returnedObjectType, converter.getConversionService()));
return RowMapperOrResultsetExtractor
.of(SingleColumnRowMapper.newInstance(returnedObjectType, converter.getConversionService()));
}
return determineDefaultMapper(queryMethod);
}
private RowMapperResultsetExtractorEither<?> determineDefaultMapper(JdbcQueryMethod queryMethod) {
private RowMapperOrResultsetExtractor<?> determineDefaultMapper(JdbcQueryMethod queryMethod) {
Class<?> domainType = queryMethod.getReturnedObjectType();
RowMapperResultsetExtractorEither<?> configuredQueryMapper = mapperMap.getMapper(domainType);
if(configuredQueryMapper != null) return configuredQueryMapper;
RowMapperOrResultsetExtractor<?> configuredQueryMapper = queryMappingConfiguration.getMapperOrExtractor(domainType);
if (configuredQueryMapper != null)
return configuredQueryMapper;
EntityRowMapper<?> defaultEntityRowMapper = new EntityRowMapper<>( //
context.getRequiredPersistentEntity(domainType), //
context, //
converter, //
accessStrategy);
return RowMapperResultsetExtractorEither.of(defaultEntityRowMapper);
return RowMapperOrResultsetExtractor.of(defaultEntityRowMapper);
}
}

View File

@@ -63,7 +63,7 @@ public class JdbcQueryMethod extends QueryMethod {
public Class<?> getRowMapperClass() {
return getMergedAnnotationAttribute("rowMapperClass");
}
/**
* Returns the class to be used as {@link org.springframework.jdbc.core.ResultSetExtractor}
*

View File

@@ -51,7 +51,7 @@ public class JdbcRepositoryFactory extends RepositoryFactorySupport {
private final DataAccessStrategy accessStrategy;
private final NamedParameterJdbcOperations operations;
private QueryMappingConfiguration mapperMap = QueryMappingConfiguration.EMPTY;
private QueryMappingConfiguration queryMappingConfiguration = QueryMappingConfiguration.EMPTY;
/**
* Creates a new {@link JdbcRepositoryFactory} for the given {@link DataAccessStrategy},
@@ -79,13 +79,14 @@ public class JdbcRepositoryFactory extends RepositoryFactorySupport {
}
/**
* @param rowMapperMap must not be {@literal null} consider {@link RowMapperMap#EMPTY} instead.
* @param queryMappingConfiguration must not be {@literal null} consider {@link QueryMappingConfiguration#EMPTY}
* instead.
*/
public void setRowMapperMap(QueryMappingConfiguration rowMapperMap) {
public void setQueryMappingConfiguration(QueryMappingConfiguration queryMappingConfiguration) {
Assert.notNull(rowMapperMap, "RowMapperMap must not be null!");
Assert.notNull(queryMappingConfiguration, "QueryMappingConfiguration must not be null!");
this.mapperMap = rowMapperMap;
this.queryMappingConfiguration = queryMappingConfiguration;
}
@SuppressWarnings("unchecked")
@@ -133,6 +134,7 @@ public class JdbcRepositoryFactory extends RepositoryFactorySupport {
throw new IllegalArgumentException(String.format("Unsupported query lookup strategy %s!", key));
}
return Optional.of(new JdbcQueryLookupStrategy(publisher, context, converter, accessStrategy, mapperMap, operations));
return Optional.of(new JdbcQueryLookupStrategy(publisher, context, converter, accessStrategy,
queryMappingConfiguration, operations));
}
}

View File

@@ -49,7 +49,7 @@ public class JdbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extend
private RelationalMappingContext mappingContext;
private RelationalConverter converter;
private DataAccessStrategy dataAccessStrategy;
private QueryMappingConfiguration mapperMap = QueryMappingConfiguration.EMPTY;
private QueryMappingConfiguration queryMappingConfiguration = QueryMappingConfiguration.EMPTY;
private NamedParameterJdbcOperations operations;
/**
@@ -81,7 +81,7 @@ public class JdbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extend
JdbcRepositoryFactory jdbcRepositoryFactory = new JdbcRepositoryFactory(dataAccessStrategy, mappingContext,
converter, publisher, operations);
jdbcRepositoryFactory.setRowMapperMap(mapperMap);
jdbcRepositoryFactory.setQueryMappingConfiguration(queryMappingConfiguration);
return jdbcRepositoryFactory;
}
@@ -102,12 +102,12 @@ public class JdbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extend
}
/**
* @param rowMapperMap can be {@literal null}. {@link #afterPropertiesSet()} defaults to {@link RowMapperMap#EMPTY} if
* {@literal null}.
* @param rowMapperMap can be {@literal null}. {@link #afterPropertiesSet()} defaults to
* {@link QueryMappingConfiguration#EMPTY} if {@literal null}.
*/
@Autowired(required = false)
public void setRowMapperMap(QueryMappingConfiguration rowMapperMap) {
this.mapperMap = rowMapperMap;
public void setQueryMappingConfiguration(QueryMappingConfiguration rowMapperMap) {
this.queryMappingConfiguration = rowMapperMap;
}
@Autowired
@@ -137,8 +137,8 @@ public class JdbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extend
operations);
}
if (mapperMap == null) {
this.mapperMap = QueryMappingConfiguration.EMPTY;
if (queryMappingConfiguration == null) {
this.queryMappingConfiguration = QueryMappingConfiguration.EMPTY;
}
super.afterPropertiesSet();

View File

@@ -15,10 +15,12 @@
*/
package org.springframework.data.jdbc.repository.support;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.jdbc.support.RowMapperResultsetExtractorEither;
import org.springframework.data.jdbc.support.RowMapperOrResultsetExtractor;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.event.AfterLoadEvent;
@@ -32,8 +34,6 @@ import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.util.List;
/**
* A query to be executed based on a repository method, it's annotated SQL query and the arguments provided to the
* method.
@@ -51,7 +51,8 @@ class JdbcRepositoryQuery implements RepositoryQuery {
private final RelationalMappingContext context;
private final JdbcQueryMethod queryMethod;
private final NamedParameterJdbcOperations operations;
private final RowMapperResultsetExtractorEither<?> mapper;
@Nullable private final RowMapperOrResultsetExtractor<?> mapperOrExtractor;
/**
* Creates a new {@link JdbcRepositoryQuery} for the given {@link JdbcQueryMethod}, {@link RelationalMappingContext}
@@ -61,10 +62,11 @@ class JdbcRepositoryQuery implements RepositoryQuery {
* @param context must not be {@literal null}.
* @param queryMethod must not be {@literal null}.
* @param operations must not be {@literal null}.
* @param defaultRowMapper can be {@literal null} (only in case of a modifying query).
* @param defaultMapper can be {@literal null} (only in case of a modifying query).
*/
JdbcRepositoryQuery(ApplicationEventPublisher publisher, RelationalMappingContext context, JdbcQueryMethod queryMethod, NamedParameterJdbcOperations operations,
@Nullable RowMapperResultsetExtractorEither<?> defaultMapper) {
JdbcRepositoryQuery(ApplicationEventPublisher publisher, RelationalMappingContext context,
JdbcQueryMethod queryMethod, NamedParameterJdbcOperations operations,
@Nullable RowMapperOrResultsetExtractor<?> defaultMapper) {
Assert.notNull(publisher, "Publisher must not be null!");
Assert.notNull(context, "Context must not be null!");
@@ -79,7 +81,7 @@ class JdbcRepositoryQuery implements RepositoryQuery {
this.context = context;
this.queryMethod = queryMethod;
this.operations = operations;
this.mapper = determineMapper(defaultMapper);
this.mapperOrExtractor = determineMapper(defaultMapper);
}
/*
@@ -100,26 +102,31 @@ class JdbcRepositoryQuery implements RepositoryQuery {
: updatedCount;
}
assert this.mapperOrExtractor != null;
if (queryMethod.isCollectionQuery() || queryMethod.isStreamQuery()) {
List<?> result = null;
if(this.mapper.isResultSetExtractor()) {
result = (List<?>) operations.query(query, parameters, this.mapper.resultSetExtractor());
} else {
result = operations.query(query, parameters, this.mapper.rowMapper());
}
List<?> result = this.mapperOrExtractor.isResultSetExtractor()
? (List<?>) operations.query(query, parameters, this.mapperOrExtractor.getResultSetExtractor())
: operations.query(query, parameters, this.mapperOrExtractor.getRowMapper());
Assert.notNull(result, "A collection valued result must never be null.");
publishAfterLoad(result);
return result;
}
try {
Object result = null;
if(this.mapper.isResultSetExtractor()) {
result = operations.query(query,parameters, this.mapper.resultSetExtractor());
} else {
result = operations.queryForObject(query, parameters, this.mapper.rowMapper());
}
Object result = this.mapperOrExtractor.isResultSetExtractor()
? operations.query(query, parameters, this.mapperOrExtractor.getResultSetExtractor())
: operations.queryForObject(query, parameters, this.mapperOrExtractor.getRowMapper());
publishAfterLoad(result);
return result;
} catch (EmptyResultDataAccessException e) {
return null;
}
@@ -158,30 +165,51 @@ class JdbcRepositoryQuery implements RepositoryQuery {
return parameters;
}
private RowMapperResultsetExtractorEither<?> determineMapper(RowMapperResultsetExtractorEither<?> defaultMapper) {
RowMapperResultsetExtractorEither<?> configuredMapper = getConfiguredMapper(queryMethod);
if(configuredMapper != null) return configuredMapper;
return defaultMapper;
}
@Nullable
private static RowMapperResultsetExtractorEither<?> getConfiguredMapper(JdbcQueryMethod queryMethod) {
private RowMapperOrResultsetExtractor<?> determineMapper(@Nullable RowMapperOrResultsetExtractor<?> defaultMapper) {
RowMapperOrResultsetExtractor<?> configuredMapper = getConfiguredMapper(queryMethod);
return (configuredMapper == null) ? defaultMapper : configuredMapper;
}
@Nullable
private static RowMapperOrResultsetExtractor<?> getConfiguredMapper(JdbcQueryMethod queryMethod) {
Class<?> rowMapperClass = queryMethod.getRowMapperClass();
Class<?> resultSetExtractorClass = queryMethod.getResultSetExtractorClass();
if(isConfigured(rowMapperClass, RowMapper.class) && isConfigured(resultSetExtractorClass, ResultSetExtractor.class))
throw new InvalidQueryConfiguration("Cannot use both rowMapperClass and resultSetExtractorClass on @Query annotation. Query method: [" + queryMethod.getName() + "] query: [" + queryMethod.getAnnotatedQuery() + "]");
if(!isConfigured(rowMapperClass, RowMapper.class) && !isConfigured(resultSetExtractorClass, ResultSetExtractor.class))
return null;
if(isConfigured(rowMapperClass, RowMapper.class)) {
return RowMapperResultsetExtractorEither.of((RowMapper<?>) BeanUtils.instantiateClass(rowMapperClass));
} else {
return RowMapperResultsetExtractorEither.of((ResultSetExtractor<?>) BeanUtils.instantiateClass(resultSetExtractorClass));
assertOnlyOneIsConfigured(queryMethod, rowMapperClass, resultSetExtractorClass);
if (isConfigured(rowMapperClass, RowMapper.class)) {
return RowMapperOrResultsetExtractor.of((RowMapper<?>) BeanUtils.instantiateClass(rowMapperClass));
}
if (isConfigured(resultSetExtractorClass, ResultSetExtractor.class)) {
return RowMapperOrResultsetExtractor
.of((ResultSetExtractor<?>) BeanUtils.instantiateClass(resultSetExtractorClass));
}
return null;
}
private static void assertOnlyOneIsConfigured(JdbcQueryMethod queryMethod, @Nullable Class<?> rowMapperClass,
@Nullable Class<?> resultSetExtractorClass) {
if (isConfigured(rowMapperClass, RowMapper.class)
&& isConfigured(resultSetExtractorClass, ResultSetExtractor.class)) {
throw new IllegalStateException( //
String.format( //
"Cannot use both rowMapperClass and resultSetExtractorClass on @Query annotation. Query // method: [%s] query: [%s]",
queryMethod.getName(), //
queryMethod.getAnnotatedQuery() //
));
}
}
private static boolean isConfigured(Class<?> rowMapperClass, Class<?> defaultClass) {
return rowMapperClass != null && rowMapperClass != defaultClass;
private static boolean isConfigured(@Nullable Class<?> configuredClass, Class<?> defaultClass) {
return configuredClass != null && configuredClass != defaultClass;
}
private <T> void publishAfterLoad(Iterable<T> all) {
@@ -196,8 +224,7 @@ class JdbcRepositoryQuery implements RepositoryQuery {
if (entity != null && context.hasPersistentEntityFor(entity.getClass())) {
RelationalPersistentEntity<?> e = context.getRequiredPersistentEntity(entity.getClass());
Object identifier = e.getIdentifierAccessor(entity)
.getIdentifier();
Object identifier = e.getIdentifierAccessor(entity).getIdentifier();
if (identifier != null) {
publisher.publishEvent(new AfterLoadEvent(Identifier.of(identifier), entity));

View File

@@ -0,0 +1,42 @@
package org.springframework.data.jdbc.support;
import lombok.Value;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;
/**
* Represents either a RowMapper or a ResultSetExtractor
*
* @author Evgeni Dimitrov
* @author Jens Schauder
*/
@Value
public class RowMapperOrResultsetExtractor<T> {
private final RowMapper<T> rowMapper;
private final ResultSetExtractor<T> resultSetExtractor;
private RowMapperOrResultsetExtractor(RowMapper<T> rowMapper, ResultSetExtractor<T> resultSetExtractor) {
this.rowMapper = rowMapper;
this.resultSetExtractor = resultSetExtractor;
}
public static RowMapperOrResultsetExtractor<?> of(RowMapper<?> rowMapper) {
return new RowMapperOrResultsetExtractor<>(rowMapper, null);
}
public static RowMapperOrResultsetExtractor<?> of(ResultSetExtractor<?> resultSetExtractor) {
return new RowMapperOrResultsetExtractor<>(null, resultSetExtractor);
}
public boolean isRowMapper() {
return this.rowMapper != null;
}
public boolean isResultSetExtractor() {
return this.resultSetExtractor != null;
}
}

View File

@@ -1,76 +0,0 @@
package org.springframework.data.jdbc.support;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;
/**
* Represents either a RowMapper or a ResultSetExtractor
*
* @author Evgeni Dimitrov
*/
public class RowMapperResultsetExtractorEither<T> {
private final RowMapper<T> rowMapper;
private final ResultSetExtractor<T> resultSetExtractor;
private RowMapperResultsetExtractorEither(RowMapper<T> rowMapper, ResultSetExtractor<T> resultSetExtractor) {
this.rowMapper = rowMapper;
this.resultSetExtractor = resultSetExtractor;
}
public static RowMapperResultsetExtractorEither<?> of(RowMapper<?> rowMapper) {
return new RowMapperResultsetExtractorEither<>(rowMapper, null);
}
public boolean isRowMapper() {
return this.rowMapper != null;
}
public RowMapper<?> rowMapper() {
return this.rowMapper;
}
public static RowMapperResultsetExtractorEither<?> of(ResultSetExtractor<?> resultSetExtractor) {
return new RowMapperResultsetExtractorEither<>(null, resultSetExtractor);
}
public boolean isResultSetExtractor() {
return this.resultSetExtractor != null;
}
public ResultSetExtractor<?> resultSetExtractor() {
return this.resultSetExtractor;
}
@Override
public String toString() {
return String.format("RowMapperResultsetExtractorEither[%s]", this.rowMapper != null ? this.rowMapper : this.resultSetExtractor);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((resultSetExtractor == null) ? 0 : resultSetExtractor.hashCode());
result = prime * result + ((rowMapper == null) ? 0 : rowMapper.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
RowMapperResultsetExtractorEither other = (RowMapperResultsetExtractorEither) obj;
if (resultSetExtractor == null) {
if (other.resultSetExtractor != null) return false;
} else {
if (!resultSetExtractor.equals(other.resultSetExtractor)) return false;
}
if (rowMapper == null) {
if (other.rowMapper != null) return false;
} else {
if (!rowMapper.equals(other.rowMapper)) return false;
}
return true;
}
}

View File

@@ -54,7 +54,9 @@ import lombok.Data;
@ContextConfiguration
@Transactional
public class JdbcRepositoryMapperMapResultSetExtractorIntegrationTests {
private static String CAR_MODEL = "ResultSetExtracotr Car";
private static String CAR_MODEL = "ResultSetExtractor Car";
@Configuration
@Import(TestConfiguration.class)
@EnableJdbcRepositories(considerNestedRepositories = true)
@@ -80,21 +82,25 @@ public class JdbcRepositoryMapperMapResultSetExtractorIntegrationTests {
@Test // DATAJDBC-290
public void customFindAllCarsPicksResultSetExtractorFromMapperMap() {
carRepository.save(new Car(null, "Some model"));
Iterable<Car> cars = carRepository.customFindAll();
assertThat(cars).hasSize(1);
assertThat(cars).allMatch(car -> CAR_MODEL.equals(car.getModel()));
}
interface CarRepository extends CrudRepository<Car, Long> {
@Query("select * from car")
public List<Car> customFindAll();
List<Car> customFindAll();
}
@Data
@AllArgsConstructor
static class Car {
@Id
@Id
private Long id;
private String model;
}

View File

@@ -15,7 +15,10 @@
*/
package org.springframework.data.jdbc.repository;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -47,9 +50,6 @@ import org.springframework.test.context.junit4.rules.SpringClassRule;
import org.springframework.test.context.junit4.rules.SpringMethodRule;
import org.springframework.transaction.annotation.Transactional;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* Very simple use cases for creation and usage of {@link ResultSetExtractor}s in JdbcRepository.
*
@@ -58,6 +58,7 @@ import lombok.Data;
@ContextConfiguration
@Transactional
public class JdbcRepositoryResultSetExtractorIntegrationTests {
@Configuration
@Import(TestConfiguration.class)
static class Config {
@@ -84,88 +85,109 @@ public class JdbcRepositoryResultSetExtractorIntegrationTests {
@Test // DATAJDBC-290
public void findAllPeopleWithAdressesReturnsEmptyWhenNoneFound() {
// NOT saving anything, so DB is empty
assertThat(personRepository.findAllPeopleWithAdresses()).isEmpty();
}
@Test // DATAJDBC-290
public void findAllPeopleWithAdressesReturnsOnePersonWithoutAdresses() {
personRepository.save(new Person(null, "Joe", null));
assertThat(personRepository.findAllPeopleWithAdresses()).hasSize(1);
}
@Test // DATAJDBC-290
@Test // DATAJDBC-290
public void findAllPeopleWithAdressesReturnsOnePersonWithAdresses() {
final String personName = "Joe";
Person savedPerson = personRepository.save(new Person(null, personName, null));
String street1 = "Klokotnitsa";
String street1 = "Some Street";
String street2 = "Some other Street";
MapSqlParameterSource paramsAddress1 = buildAddressParameters(savedPerson.getId(), street1);
template.update("insert into address (street, person_id) values (:street, :personId)",paramsAddress1);
String street2 = "bul. Hristo Botev";
template.update("insert into address (street, person_id) values (:street, :personId)", paramsAddress1);
MapSqlParameterSource paramsAddress2 = buildAddressParameters(savedPerson.getId(), street2);
template.update("insert into address (street, person_id) values (:street, :personId)",paramsAddress2);
template.update("insert into address (street, person_id) values (:street, :personId)", paramsAddress2);
List<Person> people = personRepository.findAllPeopleWithAdresses();
assertThat(people).hasSize(1);
Person person = people.get(0);
assertThat(person.getName()).isEqualTo(personName);
assertThat(person.getAdresses()).hasSize(2);
assertThat(person.getAdresses()).extracting(a -> a.getStreet()).containsExactlyInAnyOrder(street1, street2);
}
private MapSqlParameterSource buildAddressParameters(Long id, String streetName) {
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("street", streetName, Types.VARCHAR);
params.addValue("personId", id, Types.NUMERIC);
return params;
}
interface PersonRepository extends CrudRepository<Person, Long> {
@Query(value="select p.id, p.name, a.id addrId, a.street from person p left join address a on(p.id = a.person_id)",
resultSetExtractorClass=PersonResultSetExtractor.class)
public List<Person> findAllPeopleWithAdresses();
@Query(
value = "select p.id, p.name, a.id addrId, a.street from person p left join address a on(p.id = a.person_id)",
resultSetExtractorClass = PersonResultSetExtractor.class)
List<Person> findAllPeopleWithAdresses();
}
@Data
@AllArgsConstructor
static class Person {
@Id
private Long id;
@Id private Long id;
private String name;
private List<Address> adresses;
}
@Data
@AllArgsConstructor
static class Address {
@Id
private Long id;
@Id private Long id;
private String street;
}
static class PersonResultSetExtractor implements ResultSetExtractor<List<Person>> {
@Override
public List<Person> extractData(ResultSet rs) throws SQLException, DataAccessException {
Map<Long, Person> peopleById = new HashMap<>();
while(rs.next()) {
while (rs.next()) {
long personId = rs.getLong("id");
Person currentPerson = peopleById.computeIfAbsent(personId, t -> {
try {
return new Person(personId, rs.getString("name"), new ArrayList<>());
} catch (SQLException e) {
throw new RecoverableDataAccessException("Error mapping Person", e);
}
});
if(currentPerson.getAdresses() == null) currentPerson.setAdresses(new ArrayList<>());
});
if (currentPerson.getAdresses() == null) {
currentPerson.setAdresses(new ArrayList<>());
}
long addrId = rs.getLong("addrId");
if(!rs.wasNull()) {
if (!rs.wasNull()) {
currentPerson.getAdresses().add(new Address(addrId, rs.getString("street")));
}
}
return new ArrayList<Person>(peopleById.values());
return new ArrayList<>(peopleById.values());
}
}
}

View File

@@ -19,89 +19,94 @@ import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
import org.springframework.data.jdbc.support.RowMapperResultsetExtractorEither;
import org.springframework.data.jdbc.support.RowMapperOrResultsetExtractor;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;
/**
* Unit tests for {@link ConfigurableRowMapperMap}.
* Unit tests for {@link DefaultQueryMappingConfiguration}.
*
* @author Jens Schauder
* @author Evgeni Dimitrov
*/
public class ConfigurableRowMapperMapUnitTests {
@Test
@Test // DATAJDBC-166
public void freshInstanceReturnsNull() {
QueryMappingConfiguration map = new DefaultQueryMappingConfiguration();
assertThat(map.getMapper(Object.class)).isNull();
assertThat(map.getMapperOrExtractor(Object.class)).isNull();
}
@Test
@Test // DATAJDBC-166
public void returnsConfiguredInstanceForClass() {
RowMapper rowMapper = mock(RowMapper.class);
QueryMappingConfiguration map = new DefaultQueryMappingConfiguration().registerRowMapper(Object.class, rowMapper);
assertThat(map.getMapper(Object.class)).isEqualTo(RowMapperResultsetExtractorEither.of(rowMapper));
assertThat(map.getMapperOrExtractor(Object.class)).isEqualTo(RowMapperOrResultsetExtractor.of(rowMapper));
}
@Test
@Test // DATAJDBC-166
public void returnsConfiguredInstanceResultSetExtractorForClass() {
ResultSetExtractor resultSetExtractor = mock(ResultSetExtractor.class);
QueryMappingConfiguration map = new DefaultQueryMappingConfiguration().registerResultSetExtractor(Object.class, resultSetExtractor);
QueryMappingConfiguration map = new DefaultQueryMappingConfiguration().registerResultSetExtractor(Object.class,
resultSetExtractor);
assertThat(map.getMapper(Object.class)).isEqualTo(RowMapperResultsetExtractorEither.of(resultSetExtractor));
assertThat(map.getMapperOrExtractor(Object.class)).isEqualTo(RowMapperOrResultsetExtractor.of(resultSetExtractor));
}
@Test
@Test // DATAJDBC-166
public void returnsNullForClassNotConfigured() {
RowMapper rowMapper = mock(RowMapper.class);
QueryMappingConfiguration map = new DefaultQueryMappingConfiguration().registerRowMapper(Number.class, rowMapper);
assertThat(map.getMapper(Integer.class)).isNull();
assertThat(map.getMapper(String.class)).isNull();
assertThat(map.getMapperOrExtractor(Integer.class)).isNull();
assertThat(map.getMapperOrExtractor(String.class)).isNull();
}
@Test
@Test // DATAJDBC-166
public void returnsNullResultSetExtractorForClassNotConfigured() {
ResultSetExtractor resultSetExtractor = mock(ResultSetExtractor.class);
QueryMappingConfiguration map = new DefaultQueryMappingConfiguration().registerResultSetExtractor(Number.class, resultSetExtractor);
QueryMappingConfiguration map = new DefaultQueryMappingConfiguration().registerResultSetExtractor(Number.class,
resultSetExtractor);
assertThat(map.getMapper(Integer.class)).isNull();
assertThat(map.getMapper(String.class)).isNull();
assertThat(map.getMapperOrExtractor(Integer.class)).isNull();
assertThat(map.getMapperOrExtractor(String.class)).isNull();
}
@Test
@Test // DATAJDBC-166
public void returnsInstanceRegisteredForSubClass() {
RowMapper rowMapper = mock(RowMapper.class);
QueryMappingConfiguration map = new DefaultQueryMappingConfiguration().registerRowMapper(String.class, rowMapper);
assertThat(map.getMapper(Object.class)).isEqualTo(RowMapperResultsetExtractorEither.of(rowMapper));
assertThat(map.getMapperOrExtractor(Object.class)).isEqualTo(RowMapperOrResultsetExtractor.of(rowMapper));
}
@Test
@Test // DATAJDBC-290
public void returnsInstanceOfResultSetExtractorRegisteredForSubClass() {
ResultSetExtractor resultSetExtractor = mock(ResultSetExtractor.class);
QueryMappingConfiguration map = new DefaultQueryMappingConfiguration().registerResultSetExtractor(String.class, resultSetExtractor);
QueryMappingConfiguration map = new DefaultQueryMappingConfiguration().registerResultSetExtractor(String.class,
resultSetExtractor);
assertThat(map.getMapper(Object.class)).isEqualTo(RowMapperResultsetExtractorEither.of(resultSetExtractor));
assertThat(map.getMapperOrExtractor(Object.class)).isEqualTo(RowMapperOrResultsetExtractor.of(resultSetExtractor));
}
@Test
@Test // DATAJDBC-166
public void prefersExactTypeMatchClass() {
RowMapper rowMapper = mock(RowMapper.class);
@@ -111,10 +116,10 @@ public class ConfigurableRowMapperMapUnitTests {
.registerRowMapper(Integer.class, rowMapper) //
.registerRowMapper(Number.class, mock(RowMapper.class));
assertThat(map.getMapper(Integer.class)).isEqualTo(RowMapperResultsetExtractorEither.of(rowMapper));
assertThat(map.getMapperOrExtractor(Integer.class)).isEqualTo(RowMapperOrResultsetExtractor.of(rowMapper));
}
@Test
@Test // DATAJDBC-290
public void prefersExactResultSetExtractorTypeMatchClass() {
ResultSetExtractor resultSetExtractor = mock(ResultSetExtractor.class);
@@ -124,10 +129,10 @@ public class ConfigurableRowMapperMapUnitTests {
.registerResultSetExtractor(Integer.class, resultSetExtractor) //
.registerResultSetExtractor(Number.class, mock(ResultSetExtractor.class));
assertThat(map.getMapper(Integer.class)).isEqualTo(RowMapperResultsetExtractorEither.of(resultSetExtractor));
assertThat(map.getMapperOrExtractor(Integer.class)).isEqualTo(RowMapperOrResultsetExtractor.of(resultSetExtractor));
}
@Test
@Test // DATAJDBC-166
public void prefersLatestRegistrationForSuperTypeMatch() {
RowMapper rowMapper = mock(RowMapper.class);
@@ -136,10 +141,10 @@ public class ConfigurableRowMapperMapUnitTests {
.registerRowMapper(Integer.class, mock(RowMapper.class)) //
.registerRowMapper(Number.class, rowMapper);
assertThat(map.getMapper(Object.class)).isEqualTo(RowMapperResultsetExtractorEither.of(rowMapper));
assertThat(map.getMapperOrExtractor(Object.class)).isEqualTo(RowMapperOrResultsetExtractor.of(rowMapper));
}
@Test
@Test // DATAJDBC-290
public void prefersLatestRegistrationOfResultSetExtractorForSuperTypeMatch() {
ResultSetExtractor resultSetExtractor = mock(ResultSetExtractor.class);
@@ -148,6 +153,6 @@ public class ConfigurableRowMapperMapUnitTests {
.registerResultSetExtractor(Integer.class, mock(ResultSetExtractor.class)) //
.registerResultSetExtractor(Number.class, resultSetExtractor);
assertThat(map.getMapper(Object.class)).isEqualTo(RowMapperResultsetExtractorEither.of(resultSetExtractor));
assertThat(map.getMapperOrExtractor(Object.class)).isEqualTo(RowMapperOrResultsetExtractor.of(resultSetExtractor));
}
}

View File

@@ -33,7 +33,7 @@ import org.springframework.data.annotation.Id;
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositoriesIntegrationTests.TestConfiguration;
import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactoryBean;
import org.springframework.data.jdbc.support.RowMapperResultsetExtractorEither;
import org.springframework.data.jdbc.support.RowMapperOrResultsetExtractor;
import org.springframework.data.repository.CrudRepository;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;
@@ -46,12 +46,13 @@ import org.springframework.util.ReflectionUtils;
*
* @author Jens Schauder
* @author Greg Turnquist
* @author Evgeni Dimitrov
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfiguration.class)
public class EnableJdbcRepositoriesIntegrationTests {
static final Field MAPPER_MAP = ReflectionUtils.findField(JdbcRepositoryFactoryBean.class, "mapperMap");
static final Field MAPPER_MAP = ReflectionUtils.findField(JdbcRepositoryFactoryBean.class, "queryMappingConfiguration");
public static final RowMapper DUMMY_ENTITY_ROW_MAPPER = mock(RowMapper.class);
public static final RowMapper STRING_ROW_MAPPER = mock(RowMapper.class);
public static final ResultSetExtractor<Integer> INTEGER_RESULT_SET_EXTRACTOR = mock(ResultSetExtractor.class);
@@ -76,23 +77,28 @@ public class EnableJdbcRepositoriesIntegrationTests {
@Test // DATAJDBC-290
public void customResultSetExtractorConfigurationGetsPickedUp() {
QueryMappingConfiguration mapping = (QueryMappingConfiguration) ReflectionUtils.getField(MAPPER_MAP, factoryBean);
assertThat(mapping.getMapper(Integer.class)).isEqualTo(RowMapperResultsetExtractorEither.of(INTEGER_RESULT_SET_EXTRACTOR));
assertThat(mapping.getMapperOrExtractor(Integer.class))
.isEqualTo(RowMapperOrResultsetExtractor.of(INTEGER_RESULT_SET_EXTRACTOR));
}
@Test // DATAJDBC-290
public void customResultSetExtractorConfigurationIsNotPickedUpIfRowMapperIsRegisteredForTheSameType() {
QueryMappingConfiguration mapping = (QueryMappingConfiguration) ReflectionUtils.getField(MAPPER_MAP, factoryBean);
assertThat(mapping.getMapper(String.class).isResultSetExtractor()).isFalse();
assertThat(mapping.getMapperOrExtractor(String.class).isResultSetExtractor()).isFalse();
}
@Test // DATAJDBC-166
public void customRowMapperConfigurationGetsPickedUp() {
QueryMappingConfiguration mapping = (QueryMappingConfiguration) ReflectionUtils.getField(MAPPER_MAP, factoryBean);
assertThat(mapping.getMapper(String.class)).isEqualTo(RowMapperResultsetExtractorEither.of(STRING_ROW_MAPPER));
assertThat(mapping.getMapper(DummyEntity.class)).isEqualTo(RowMapperResultsetExtractorEither.of(DUMMY_ENTITY_ROW_MAPPER));
assertThat(mapping.getMapperOrExtractor(String.class))
.isEqualTo(RowMapperOrResultsetExtractor.of(STRING_ROW_MAPPER));
assertThat(mapping.getMapperOrExtractor(DummyEntity.class))
.isEqualTo(RowMapperOrResultsetExtractor.of(DUMMY_ENTITY_ROW_MAPPER));
}
interface DummyRepository extends CrudRepository<DummyEntity, Long> {
@@ -116,6 +122,7 @@ public class EnableJdbcRepositoriesIntegrationTests {
@Bean
QueryMappingConfiguration rowMappers() {
return new DefaultQueryMappingConfiguration() //
.registerRowMapper(DummyEntity.class, DUMMY_ENTITY_ROW_MAPPER) //
.registerRowMapper(String.class, STRING_ROW_MAPPER)

View File

@@ -49,6 +49,7 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
* @author Oliver Gierke
* @author Mark Paluch
* @author Maciej Walkowiak
* @author Evgeni Dimitrov
*/
public class JdbcQueryLookupStrategyUnitTests {
@@ -75,9 +76,9 @@ public class JdbcQueryLookupStrategyUnitTests {
public void typeBasedRowMapperGetsUsedForQuery() {
RowMapper<? extends NumberFormat> numberFormatMapper = mock(RowMapper.class);
QueryMappingConfiguration rowMapperMap = new DefaultQueryMappingConfiguration().registerRowMapper(NumberFormat.class, numberFormatMapper);
QueryMappingConfiguration mappingConfiguration = new DefaultQueryMappingConfiguration().registerRowMapper(NumberFormat.class, numberFormatMapper);
RepositoryQuery repositoryQuery = getRepositoryQuery("returningNumberFormat", rowMapperMap);
RepositoryQuery repositoryQuery = getRepositoryQuery("returningNumberFormat", mappingConfiguration);
repositoryQuery.execute(new Object[] {});
@@ -89,19 +90,19 @@ public class JdbcQueryLookupStrategyUnitTests {
public void typeBasedResultSetExtractorGetsUsedForQuery() {
ResultSetExtractor<? extends NumberFormat> numberFormatMapper = mock(ResultSetExtractor.class);
QueryMappingConfiguration rowMapperMap = new DefaultQueryMappingConfiguration().registerResultSetExtractor(NumberFormat.class, numberFormatMapper);
QueryMappingConfiguration mappingConfiguration = new DefaultQueryMappingConfiguration().registerResultSetExtractor(NumberFormat.class, numberFormatMapper);
RepositoryQuery repositoryQuery = getRepositoryQuery("returningNumberFormat", rowMapperMap);
RepositoryQuery repositoryQuery = getRepositoryQuery("returningNumberFormat", mappingConfiguration);
repositoryQuery.execute(new Object[] {});
verify(operations).query(anyString(), any(SqlParameterSource.class), eq(numberFormatMapper));
}
private RepositoryQuery getRepositoryQuery(String name, QueryMappingConfiguration rowMapperMap) {
private RepositoryQuery getRepositoryQuery(String name, QueryMappingConfiguration mappingConfiguration) {
JdbcQueryLookupStrategy queryLookupStrategy = new JdbcQueryLookupStrategy(publisher, mappingContext, converter, accessStrategy,
rowMapperMap, operations);
mappingConfiguration, operations);
return queryLookupStrategy.resolveQuery(getMethod(name), metadata, projectionFactory, namedQueries);
}

View File

@@ -43,6 +43,8 @@ import org.springframework.test.util.ReflectionTestUtils;
* @author Christoph Strobl
* @author Oliver Gierke
* @author Mark Paluch
* @author Evgeni Dimitrov
*
*/
@RunWith(MockitoJUnitRunner.class)
public class JdbcRepositoryFactoryBeanUnitTests {
@@ -100,7 +102,7 @@ public class JdbcRepositoryFactoryBeanUnitTests {
assertThat(factoryBean.getObject()).isNotNull();
assertThat(ReflectionTestUtils.getField(factoryBean, "dataAccessStrategy"))
.isInstanceOf(DefaultDataAccessStrategy.class);
assertThat(ReflectionTestUtils.getField(factoryBean, "mapperMap")).isEqualTo(QueryMappingConfiguration.EMPTY);
assertThat(ReflectionTestUtils.getField(factoryBean, "queryMappingConfiguration")).isEqualTo(QueryMappingConfiguration.EMPTY);
}
private static class DummyEntity {

View File

@@ -30,7 +30,7 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.dao.DataAccessException;
import org.springframework.data.jdbc.support.RowMapperResultsetExtractorEither;
import org.springframework.data.jdbc.support.RowMapperOrResultsetExtractor;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.event.AfterLoadEvent;
import org.springframework.data.repository.query.DefaultParameters;
@@ -46,6 +46,7 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
* @author Jens Schauder
* @author Oliver Gierke
* @author Maciej Walkowiak
* @author Evgeni Dimitrov
*/
public class JdbcRepositoryQueryUnitTests {
@@ -72,7 +73,7 @@ public class JdbcRepositoryQueryUnitTests {
this.publisher = mock(ApplicationEventPublisher.class);
this.context = mock(RelationalMappingContext.class, RETURNS_DEEP_STUBS);
this.query = new JdbcRepositoryQuery(publisher, context, queryMethod, operations, RowMapperResultsetExtractorEither.of(defaultRowMapper));
this.query = new JdbcRepositoryQuery(publisher, context, queryMethod, operations, RowMapperOrResultsetExtractor.of(defaultRowMapper));
}
@Test // DATAJDBC-165
@@ -111,7 +112,7 @@ public class JdbcRepositoryQueryUnitTests {
doReturn("some sql statement").when(queryMethod).getAnnotatedQuery();
doReturn(CustomRowMapper.class).when(queryMethod).getRowMapperClass();
new JdbcRepositoryQuery(publisher, context, queryMethod, operations, RowMapperResultsetExtractorEither.of(defaultRowMapper)).execute(new Object[] {});
new JdbcRepositoryQuery(publisher, context, queryMethod, operations, RowMapperOrResultsetExtractor.of(defaultRowMapper)).execute(new Object[] {});
verify(operations) //
.queryForObject(anyString(), any(SqlParameterSource.class), isA(CustomRowMapper.class));
@@ -123,7 +124,7 @@ public class JdbcRepositoryQueryUnitTests {
doReturn("some sql statement").when(queryMethod).getAnnotatedQuery();
doReturn(CustomResultSetExtractor.class).when(queryMethod).getResultSetExtractorClass();
new JdbcRepositoryQuery(publisher, context, queryMethod, operations, RowMapperResultsetExtractorEither.of(defaultRowMapper)).execute(new Object[] {});
new JdbcRepositoryQuery(publisher, context, queryMethod, operations, RowMapperOrResultsetExtractor.of(defaultRowMapper)).execute(new Object[] {});
verify(operations) //
.query(anyString(), any(SqlParameterSource.class), isA(CustomResultSetExtractor.class));
@@ -139,7 +140,7 @@ public class JdbcRepositoryQueryUnitTests {
doReturn(true).when(context).hasPersistentEntityFor(DummyEntity.class);
when(context.getRequiredPersistentEntity(DummyEntity.class).getIdentifierAccessor(any()).getRequiredIdentifier()).thenReturn("some identifier");
new JdbcRepositoryQuery(publisher, context, queryMethod, operations, RowMapperResultsetExtractorEither.of(defaultRowMapper)).execute(new Object[] {});
new JdbcRepositoryQuery(publisher, context, queryMethod, operations, RowMapperOrResultsetExtractor.of(defaultRowMapper)).execute(new Object[] {});
verify(publisher).publishEvent(any(AfterLoadEvent.class));
}
@@ -153,7 +154,7 @@ public class JdbcRepositoryQueryUnitTests {
doReturn(true).when(context).hasPersistentEntityFor(DummyEntity.class);
when(context.getRequiredPersistentEntity(DummyEntity.class).getIdentifierAccessor(any()).getRequiredIdentifier()).thenReturn("some identifier");
new JdbcRepositoryQuery(publisher, context, queryMethod, operations, RowMapperResultsetExtractorEither.of(defaultRowMapper)).execute(new Object[] {});
new JdbcRepositoryQuery(publisher, context, queryMethod, operations, RowMapperOrResultsetExtractor.of(defaultRowMapper)).execute(new Object[] {});
verify(publisher, times(2)).publishEvent(any(AfterLoadEvent.class));
}