Consider QueryMappingConfiguration for part tree queries.
Signed-off-by: mipo256 <mikhailpolivakha@gmail.com> Commit message edited by Jens Schauder Original pull request #1893 Closes #1006
This commit is contained in:
@@ -15,7 +15,10 @@
|
||||
*/
|
||||
package org.springframework.data.jdbc.core.convert;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -25,6 +28,7 @@ import org.springframework.util.Assert;
|
||||
* {@link DataAccessStrategy} for consistent access strategy creation.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Mikhail Polivakha
|
||||
* @since 3.2
|
||||
*/
|
||||
public class DataAccessStrategyFactory {
|
||||
@@ -34,6 +38,7 @@ public class DataAccessStrategyFactory {
|
||||
private final NamedParameterJdbcOperations operations;
|
||||
private final SqlParametersFactory sqlParametersFactory;
|
||||
private final InsertStrategyFactory insertStrategyFactory;
|
||||
private final QueryMappingConfiguration queryMappingConfiguration;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DataAccessStrategyFactory}.
|
||||
@@ -43,22 +48,25 @@ public class DataAccessStrategyFactory {
|
||||
* @param operations must not be {@literal null}.
|
||||
* @param sqlParametersFactory must not be {@literal null}.
|
||||
* @param insertStrategyFactory must not be {@literal null}.
|
||||
* @param queryMappingConfiguration must not be {@literal null}.
|
||||
*/
|
||||
public DataAccessStrategyFactory(SqlGeneratorSource sqlGeneratorSource, JdbcConverter converter,
|
||||
NamedParameterJdbcOperations operations, SqlParametersFactory sqlParametersFactory,
|
||||
InsertStrategyFactory insertStrategyFactory) {
|
||||
InsertStrategyFactory insertStrategyFactory, QueryMappingConfiguration queryMappingConfiguration) {
|
||||
|
||||
Assert.notNull(sqlGeneratorSource, "SqlGeneratorSource must not be null");
|
||||
Assert.notNull(converter, "JdbcConverter must not be null");
|
||||
Assert.notNull(operations, "NamedParameterJdbcOperations must not be null");
|
||||
Assert.notNull(sqlParametersFactory, "SqlParametersFactory must not be null");
|
||||
Assert.notNull(insertStrategyFactory, "InsertStrategyFactory must not be null");
|
||||
Assert.notNull(queryMappingConfiguration, "QueryMappingConfiguration must not be null");
|
||||
|
||||
this.sqlGeneratorSource = sqlGeneratorSource;
|
||||
this.converter = converter;
|
||||
this.operations = operations;
|
||||
this.sqlParametersFactory = sqlParametersFactory;
|
||||
this.insertStrategyFactory = insertStrategyFactory;
|
||||
this.queryMappingConfiguration = queryMappingConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,7 +78,7 @@ public class DataAccessStrategyFactory {
|
||||
|
||||
DefaultDataAccessStrategy defaultDataAccessStrategy = new DefaultDataAccessStrategy(sqlGeneratorSource,
|
||||
this.converter.getMappingContext(), this.converter, this.operations, sqlParametersFactory,
|
||||
insertStrategyFactory);
|
||||
insertStrategyFactory, queryMappingConfiguration);
|
||||
|
||||
if (this.converter.getMappingContext().isSingleQueryLoadingEnabled()) {
|
||||
return new SingleQueryFallbackDataAccessStrategy(sqlGeneratorSource, converter, operations,
|
||||
|
||||
@@ -62,6 +62,7 @@ import org.springframework.util.Assert;
|
||||
* @author Chirag Tailor
|
||||
* @author Diego Krupitza
|
||||
* @author Sergey Korotaev
|
||||
* @author Mikhail Polivakha
|
||||
* @since 1.1
|
||||
*/
|
||||
public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
@@ -73,6 +74,8 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
private final SqlParametersFactory sqlParametersFactory;
|
||||
private final InsertStrategyFactory insertStrategyFactory;
|
||||
|
||||
private final QueryMappingConfiguration queryMappingConfiguration;
|
||||
|
||||
/**
|
||||
* Creates a {@link DefaultDataAccessStrategy}
|
||||
*
|
||||
@@ -84,7 +87,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
*/
|
||||
public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, RelationalMappingContext context,
|
||||
JdbcConverter converter, NamedParameterJdbcOperations operations, SqlParametersFactory sqlParametersFactory,
|
||||
InsertStrategyFactory insertStrategyFactory) {
|
||||
InsertStrategyFactory insertStrategyFactory, QueryMappingConfiguration queryMappingConfiguration) {
|
||||
|
||||
Assert.notNull(sqlGeneratorSource, "SqlGeneratorSource must not be null");
|
||||
Assert.notNull(context, "RelationalMappingContext must not be null");
|
||||
@@ -92,6 +95,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
Assert.notNull(operations, "NamedParameterJdbcOperations must not be null");
|
||||
Assert.notNull(sqlParametersFactory, "SqlParametersFactory must not be null");
|
||||
Assert.notNull(insertStrategyFactory, "InsertStrategyFactory must not be null");
|
||||
Assert.notNull(queryMappingConfiguration, "QueryMappingConfiguration must not be null");
|
||||
|
||||
this.sqlGeneratorSource = sqlGeneratorSource;
|
||||
this.context = context;
|
||||
@@ -99,6 +103,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
this.operations = operations;
|
||||
this.sqlParametersFactory = sqlParametersFactory;
|
||||
this.insertStrategyFactory = insertStrategyFactory;
|
||||
this.queryMappingConfiguration = queryMappingConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -272,7 +277,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
SqlIdentifierParameterSource parameter = sqlParametersFactory.forQueryById(id, domainType, ID_SQL_PARAMETER);
|
||||
|
||||
try {
|
||||
return operations.queryForObject(findOneSql, parameter, getEntityRowMapper(domainType));
|
||||
return operations.queryForObject(findOneSql, parameter, getRowMapper(domainType));
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
return null;
|
||||
}
|
||||
@@ -280,13 +285,13 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
|
||||
@Override
|
||||
public <T> List<T> findAll(Class<T> domainType) {
|
||||
return operations.query(sql(domainType).getFindAll(), getEntityRowMapper(domainType));
|
||||
return operations.query(sql(domainType).getFindAll(), getRowMapper(domainType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Stream<T> streamAll(Class<T> domainType) {
|
||||
return operations.queryForStream(sql(domainType).getFindAll(), new MapSqlParameterSource(),
|
||||
getEntityRowMapper(domainType));
|
||||
getRowMapper(domainType));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -298,7 +303,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
|
||||
SqlParameterSource parameterSource = sqlParametersFactory.forQueryByIds(ids, domainType);
|
||||
String findAllInListSql = sql(domainType).getFindAllInList();
|
||||
return operations.query(findAllInListSql, parameterSource, getEntityRowMapper(domainType));
|
||||
return operations.query(findAllInListSql, parameterSource, getRowMapper(domainType));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -311,7 +316,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
SqlParameterSource parameterSource = sqlParametersFactory.forQueryByIds(ids, domainType);
|
||||
String findAllInListSql = sql(domainType).getFindAllInList();
|
||||
|
||||
return operations.queryForStream(findAllInListSql, parameterSource, getEntityRowMapper(domainType));
|
||||
return operations.queryForStream(findAllInListSql, parameterSource, getRowMapper(domainType));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -365,18 +370,18 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
|
||||
@Override
|
||||
public <T> List<T> findAll(Class<T> domainType, Sort sort) {
|
||||
return operations.query(sql(domainType).getFindAll(sort), getEntityRowMapper(domainType));
|
||||
return operations.query(sql(domainType).getFindAll(sort), getRowMapper(domainType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Stream<T> streamAll(Class<T> domainType, Sort sort) {
|
||||
return operations.queryForStream(sql(domainType).getFindAll(sort), new MapSqlParameterSource(),
|
||||
getEntityRowMapper(domainType));
|
||||
getRowMapper(domainType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> findAll(Class<T> domainType, Pageable pageable) {
|
||||
return operations.query(sql(domainType).getFindAll(pageable), getEntityRowMapper(domainType));
|
||||
return operations.query(sql(domainType).getFindAll(pageable), getRowMapper(domainType));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -386,7 +391,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
String sqlQuery = sql(domainType).selectByQuery(query, parameterSource);
|
||||
|
||||
try {
|
||||
return Optional.ofNullable(operations.queryForObject(sqlQuery, parameterSource, getEntityRowMapper(domainType)));
|
||||
return Optional.ofNullable(operations.queryForObject(sqlQuery, parameterSource, getRowMapper(domainType)));
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
@@ -398,7 +403,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
|
||||
String sqlQuery = sql(domainType).selectByQuery(query, parameterSource);
|
||||
|
||||
return operations.query(sqlQuery, parameterSource, getEntityRowMapper(domainType));
|
||||
return operations.query(sqlQuery, parameterSource, getRowMapper(domainType));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -407,7 +412,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
|
||||
String sqlQuery = sql(domainType).selectByQuery(query, parameterSource);
|
||||
|
||||
return operations.queryForStream(sqlQuery, parameterSource, getEntityRowMapper(domainType));
|
||||
return operations.queryForStream(sqlQuery, parameterSource, getRowMapper(domainType));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -416,7 +421,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
|
||||
String sqlQuery = sql(domainType).selectByQuery(query, parameterSource, pageable);
|
||||
|
||||
return operations.query(sqlQuery, parameterSource, getEntityRowMapper(domainType));
|
||||
return operations.query(sqlQuery, parameterSource, getRowMapper(domainType));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -445,7 +450,13 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
return result;
|
||||
}
|
||||
|
||||
private <T> EntityRowMapper<T> getEntityRowMapper(Class<T> domainType) {
|
||||
private <T> RowMapper<? extends T> getRowMapper(Class<T> domainType) {
|
||||
RowMapper<? extends T> targetRowMapper;
|
||||
|
||||
if ((targetRowMapper = queryMappingConfiguration.getRowMapper(domainType)) != null) {
|
||||
return targetRowMapper;
|
||||
}
|
||||
|
||||
return new EntityRowMapper<>(getRequiredPersistentEntity(domainType), converter);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.data.jdbc.repository;
|
||||
package org.springframework.data.jdbc.core.convert;
|
||||
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -32,6 +32,7 @@ import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jdbc.core.convert.*;
|
||||
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
|
||||
import org.springframework.data.mapping.PersistentPropertyPath;
|
||||
import org.springframework.data.mapping.PropertyPath;
|
||||
import org.springframework.data.relational.core.conversion.IdValueSource;
|
||||
@@ -76,9 +77,10 @@ public class MyBatisDataAccessStrategy implements DataAccessStrategy {
|
||||
* uses a {@link DefaultDataAccessStrategy}
|
||||
*/
|
||||
public static DataAccessStrategy createCombinedAccessStrategy(RelationalMappingContext context,
|
||||
JdbcConverter converter, NamedParameterJdbcOperations operations, SqlSession sqlSession, Dialect dialect) {
|
||||
JdbcConverter converter, NamedParameterJdbcOperations operations, SqlSession sqlSession,
|
||||
Dialect dialect, QueryMappingConfiguration queryMappingConfiguration) {
|
||||
return createCombinedAccessStrategy(context, converter, operations, sqlSession, NamespaceStrategy.DEFAULT_INSTANCE,
|
||||
dialect);
|
||||
dialect, queryMappingConfiguration);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,7 +89,7 @@ public class MyBatisDataAccessStrategy implements DataAccessStrategy {
|
||||
*/
|
||||
public static DataAccessStrategy createCombinedAccessStrategy(RelationalMappingContext context,
|
||||
JdbcConverter converter, NamedParameterJdbcOperations operations, SqlSession sqlSession,
|
||||
NamespaceStrategy namespaceStrategy, Dialect dialect) {
|
||||
NamespaceStrategy namespaceStrategy, Dialect dialect, QueryMappingConfiguration queryMappingConfiguration) {
|
||||
|
||||
SqlGeneratorSource sqlGeneratorSource = new SqlGeneratorSource(context, converter, dialect);
|
||||
SqlParametersFactory sqlParametersFactory = new SqlParametersFactory(context, converter);
|
||||
@@ -98,7 +100,8 @@ public class MyBatisDataAccessStrategy implements DataAccessStrategy {
|
||||
converter, //
|
||||
operations, //
|
||||
sqlParametersFactory, //
|
||||
insertStrategyFactory //
|
||||
insertStrategyFactory, //
|
||||
queryMappingConfiguration //
|
||||
).create();
|
||||
|
||||
// the DefaultDataAccessStrategy needs a reference to the returned DataAccessStrategy. This creates a dependency
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.springframework.data.jdbc.core.dialect.JdbcArrayColumns;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcDialect;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcSimpleTypes;
|
||||
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.relational.RelationalManagedTypes;
|
||||
import org.springframework.data.relational.core.conversion.RelationalConverter;
|
||||
@@ -63,6 +64,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Christoph Strobl
|
||||
* @author Myeonghyeon Lee
|
||||
* @author Chirag Tailor
|
||||
* @author Mikhail Polivakha
|
||||
* @since 1.1
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@@ -72,6 +74,8 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware {
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private QueryMappingConfiguration queryMappingConfiguration = QueryMappingConfiguration.EMPTY;
|
||||
|
||||
/**
|
||||
* Returns the base packages to scan for JDBC mapped entities at startup. Returns the package name of the
|
||||
* configuration class' (the concrete class, not this one here) by default. So if you have a
|
||||
@@ -224,7 +228,9 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware {
|
||||
|
||||
SqlGeneratorSource sqlGeneratorSource = new SqlGeneratorSource(context, jdbcConverter, dialect);
|
||||
DataAccessStrategyFactory factory = new DataAccessStrategyFactory(sqlGeneratorSource, jdbcConverter, operations,
|
||||
new SqlParametersFactory(context, jdbcConverter), new InsertStrategyFactory(operations, dialect));
|
||||
new SqlParametersFactory(context, jdbcConverter), new InsertStrategyFactory(operations, dialect),
|
||||
this.queryMappingConfiguration
|
||||
);
|
||||
|
||||
return factory.create();
|
||||
}
|
||||
@@ -248,6 +254,10 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public void setQueryMappingConfiguration(Optional<QueryMappingConfiguration> queryMappingConfiguration) throws BeansException {
|
||||
this.queryMappingConfiguration = queryMappingConfiguration.orElse(QueryMappingConfiguration.EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the mapping base package for classes annotated with {@link Table}. By default, it scans for entities in all
|
||||
* packages returned by {@link #getMappingBasePackages()}.
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.springframework.data.jdbc.repository.config;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
|
||||
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.jdbc.repository.config;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -23,6 +25,7 @@ import org.springframework.data.jdbc.core.convert.DataAccessStrategy;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcConverter;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
|
||||
import org.springframework.data.jdbc.mybatis.MyBatisDataAccessStrategy;
|
||||
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
|
||||
import org.springframework.data.relational.core.dialect.Dialect;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
|
||||
|
||||
@@ -30,6 +33,7 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
|
||||
* Configuration class tweaking Spring Data JDBC to use a {@link MyBatisDataAccessStrategy} instead of the default one.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
* @author Mikhail Polivakha
|
||||
* @since 1.1
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@@ -37,11 +41,13 @@ public class MyBatisJdbcConfiguration extends AbstractJdbcConfiguration {
|
||||
|
||||
private @Autowired SqlSession session;
|
||||
|
||||
private @Autowired Optional<QueryMappingConfiguration> queryMappingConfiguration;
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public DataAccessStrategy dataAccessStrategyBean(NamedParameterJdbcOperations operations, JdbcConverter jdbcConverter,
|
||||
JdbcMappingContext context, Dialect dialect) {
|
||||
|
||||
return MyBatisDataAccessStrategy.createCombinedAccessStrategy(context, jdbcConverter, operations, session, dialect);
|
||||
return MyBatisDataAccessStrategy.createCombinedAccessStrategy(context, jdbcConverter, operations, session, dialect, queryMappingConfiguration.orElse(QueryMappingConfiguration.EMPTY));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcConverter;
|
||||
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.repository.query.DefaultRowMapperFactory;
|
||||
import org.springframework.data.jdbc.repository.query.JdbcQueryMethod;
|
||||
import org.springframework.data.jdbc.repository.query.PartTreeJdbcQuery;
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.data.jdbc.core.JdbcAggregateTemplate;
|
||||
import org.springframework.data.jdbc.core.convert.DataAccessStrategy;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcConverter;
|
||||
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
|
||||
import org.springframework.data.mapping.callback.EntityCallbacks;
|
||||
import org.springframework.data.relational.core.dialect.Dialect;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.springframework.data.jdbc.core.convert.InsertStrategyFactory;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcConverter;
|
||||
import org.springframework.data.jdbc.core.convert.SqlGeneratorSource;
|
||||
import org.springframework.data.jdbc.core.convert.SqlParametersFactory;
|
||||
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
|
||||
import org.springframework.data.mapping.callback.EntityCallbacks;
|
||||
import org.springframework.data.relational.core.dialect.Dialect;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
@@ -48,6 +48,7 @@ import org.springframework.util.Assert;
|
||||
* @author Mark Paluch
|
||||
* @author Hebert Coelho
|
||||
* @author Chirag Tailor
|
||||
* @author Mikhail Polivakha
|
||||
*/
|
||||
public class JdbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
|
||||
extends TransactionalRepositoryFactoryBeanSupport<T, S, ID> implements ApplicationEventPublisherAware {
|
||||
@@ -166,6 +167,10 @@ public class JdbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extend
|
||||
this.operations = beanFactory.getBean(NamedParameterJdbcOperations.class);
|
||||
}
|
||||
|
||||
if (this.queryMappingConfiguration == null) {
|
||||
this.queryMappingConfiguration = QueryMappingConfiguration.EMPTY;
|
||||
}
|
||||
|
||||
if (this.dataAccessStrategy == null) {
|
||||
|
||||
Assert.state(beanFactory != null, "If no DataAccessStrategy is set a BeanFactory must be available");
|
||||
@@ -181,16 +186,12 @@ public class JdbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extend
|
||||
InsertStrategyFactory insertStrategyFactory = new InsertStrategyFactory(this.operations, this.dialect);
|
||||
|
||||
DataAccessStrategyFactory factory = new DataAccessStrategyFactory(sqlGeneratorSource, this.converter,
|
||||
this.operations, sqlParametersFactory, insertStrategyFactory);
|
||||
this.operations, sqlParametersFactory, insertStrategyFactory, queryMappingConfiguration);
|
||||
|
||||
return factory.create();
|
||||
});
|
||||
}
|
||||
|
||||
if (this.queryMappingConfiguration == null) {
|
||||
this.queryMappingConfiguration = QueryMappingConfiguration.EMPTY;
|
||||
}
|
||||
|
||||
if (beanFactory != null) {
|
||||
entityCallbacks = EntityCallbacks.create(beanFactory);
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ public class DependencyTests {
|
||||
"org.springframework.data.jdbc", // Spring Data Relational
|
||||
"org.springframework.data.relational", // Spring Data Relational
|
||||
"org.springframework.data" // Spring Data Commons
|
||||
).that(onlySpringData()) //
|
||||
)
|
||||
.that(ignore(AuditingHandlerBeanDefinitionParser.class)) //
|
||||
.that(ignorePackage("org.springframework.data.aot.hint")) // ignoring aot, since it causes cycles in commons
|
||||
.that(ignorePackage("org.springframework.data.aot")); // ignoring aot, since it causes cycles in commons
|
||||
|
||||
@@ -40,6 +40,7 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
|
||||
* @author Myat Min
|
||||
* @author Radim Tlusty
|
||||
* @author Chirag Tailor
|
||||
* @author Mikhail Polivakha
|
||||
*/
|
||||
class DefaultDataAccessStrategyUnitTests {
|
||||
|
||||
@@ -66,7 +67,8 @@ class DefaultDataAccessStrategyUnitTests {
|
||||
converter, //
|
||||
namedJdbcOperations, //
|
||||
sqlParametersFactory, //
|
||||
insertStrategyFactory).create();
|
||||
insertStrategyFactory,
|
||||
QueryMappingConfiguration.EMPTY).create();
|
||||
|
||||
relationResolver.setDelegate(accessStrategy);
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.data.jdbc.core.convert.DataAccessStrategy;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcConverter;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcHsqlDbDialect;
|
||||
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;
|
||||
import org.springframework.data.jdbc.testing.DatabaseType;
|
||||
import org.springframework.data.jdbc.testing.EnabledOnDatabase;
|
||||
@@ -49,6 +50,7 @@ import junit.framework.AssertionFailedError;
|
||||
* @author Jens Schauder
|
||||
* @author Greg Turnquist
|
||||
* @author Mark Paluch
|
||||
* @author Mikhail Polivakha
|
||||
*/
|
||||
@IntegrationTest
|
||||
@EnabledOnDatabase(DatabaseType.HSQL)
|
||||
@@ -119,7 +121,7 @@ public class MyBatisHsqlIntegrationTests {
|
||||
SqlSession sqlSession, EmbeddedDatabase db) {
|
||||
|
||||
return MyBatisDataAccessStrategy.createCombinedAccessStrategy(context, converter,
|
||||
new NamedParameterJdbcTemplate(db), sqlSession, JdbcHsqlDbDialect.INSTANCE);
|
||||
new NamedParameterJdbcTemplate(db), sqlSession, JdbcHsqlDbDialect.INSTANCE, QueryMappingConfiguration.EMPTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
package org.springframework.data.jdbc.repository;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.repository.config.DefaultQueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;
|
||||
import org.springframework.data.jdbc.repository.query.PartTreeJdbcQuery;
|
||||
import org.springframework.data.jdbc.testing.IntegrationTest;
|
||||
import org.springframework.data.jdbc.testing.TestConfiguration;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
/**
|
||||
* Tests for mapping the results of {@link PartTreeJdbcQuery} execution via custom {@link QueryMappingConfiguration}
|
||||
*
|
||||
* @author Mikhail Polivakha
|
||||
*/
|
||||
@IntegrationTest
|
||||
public class PartTreeQueryMappingConfigurationIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
@Import(TestConfiguration.class)
|
||||
@EnableJdbcRepositories(
|
||||
considerNestedRepositories = true,
|
||||
includeFilters = @ComponentScan.Filter(value = CarRepository.class, type = FilterType.ASSIGNABLE_TYPE))
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
QueryMappingConfiguration mappers(@Qualifier("CustomRowMapperBean") CustomRowMapperBean rowMapperBean) {
|
||||
return new DefaultQueryMappingConfiguration().registerRowMapper(Car.class, rowMapperBean);
|
||||
}
|
||||
|
||||
@Bean(value = "CustomRowMapperBean")
|
||||
public CustomRowMapperBean rowMapperBean() {
|
||||
return new CustomRowMapperBean();
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private CarRepository carRepository;
|
||||
|
||||
@Test // DATAJDBC-1006
|
||||
void testCustomQueryMappingConfiguration_predefinedPartTreeQuery() {
|
||||
|
||||
// given
|
||||
Car saved = carRepository.save(new Car(null, "test-model"));
|
||||
|
||||
// when
|
||||
Optional<Car> found = carRepository.findById(saved.getId());
|
||||
|
||||
// then
|
||||
Assertions.assertThat(found).isPresent().hasValueSatisfying(car -> Assertions.assertThat(car.getModel()).isEqualTo("STUB"));
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-1006
|
||||
void testCustomQueryMappingConfiguration_customPartTreeQuery() {
|
||||
|
||||
// given
|
||||
Car saved = carRepository.save(new Car(null, "test-model"));
|
||||
|
||||
// when
|
||||
Optional<Car> found = carRepository.findOneByModel("test-model");
|
||||
|
||||
// then
|
||||
Assertions.assertThat(found).isPresent().hasValueSatisfying(car -> Assertions.assertThat(car.getModel()).isEqualTo("STUB"));
|
||||
}
|
||||
|
||||
public static class CustomRowMapperBean implements RowMapper<Car> {
|
||||
|
||||
@Override
|
||||
public Car mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
return new Car(rs.getLong("id"), "STUB");
|
||||
}
|
||||
}
|
||||
|
||||
interface CarRepository extends CrudRepository<Car, Long> {
|
||||
|
||||
Optional<Car> findOneByModel(String model);
|
||||
}
|
||||
|
||||
public static class Car {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
private String model;
|
||||
|
||||
public Car(Long id, String model) {
|
||||
this.id = id;
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String getModel() {
|
||||
return this.model;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setModel(String model) {
|
||||
this.model = model;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,17 +38,8 @@ import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jdbc.core.convert.DefaultDataAccessStrategy;
|
||||
import org.springframework.data.jdbc.core.convert.DefaultJdbcTypeFactory;
|
||||
import org.springframework.data.jdbc.core.convert.DelegatingDataAccessStrategy;
|
||||
import org.springframework.data.jdbc.core.convert.InsertStrategyFactory;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcConverter;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcCustomConversions;
|
||||
import org.springframework.data.jdbc.core.convert.MappingJdbcConverter;
|
||||
import org.springframework.data.jdbc.core.convert.SqlGeneratorSource;
|
||||
import org.springframework.data.jdbc.core.convert.SqlParametersFactory;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcH2Dialect;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcHsqlDbDialect;
|
||||
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.core.convert.*;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
|
||||
import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory;
|
||||
import org.springframework.data.jdbc.repository.support.SimpleJdbcRepository;
|
||||
@@ -83,6 +74,7 @@ import org.springframework.util.ObjectUtils;
|
||||
* @author Milan Milanov
|
||||
* @author Myeonghyeon Lee
|
||||
* @author Chirag Tailor
|
||||
* @author Mikhail Polivakha
|
||||
*/
|
||||
class SimpleJdbcRepositoryEventsUnitTests {
|
||||
|
||||
@@ -108,7 +100,7 @@ class SimpleJdbcRepositoryEventsUnitTests {
|
||||
InsertStrategyFactory insertStrategyFactory = new InsertStrategyFactory(operations, dialect);
|
||||
|
||||
this.dataAccessStrategy = spy(new DefaultDataAccessStrategy(generatorSource, context, converter, operations,
|
||||
sqlParametersFactory, insertStrategyFactory));
|
||||
sqlParametersFactory, insertStrategyFactory, QueryMappingConfiguration.EMPTY));
|
||||
delegatingDataAccessStrategy.setDelegate(dataAccessStrategy);
|
||||
doReturn(true).when(dataAccessStrategy).update(any(), any());
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.repository.config.DefaultQueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;
|
||||
import org.springframework.data.jdbc.repository.query.Query;
|
||||
@@ -60,7 +61,7 @@ public class StringBasedJdbcQueryMappingConfigurationIntegrationTests {
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
QueryMappingConfiguration mappers() {
|
||||
QueryMappingConfiguration mappers() {
|
||||
return new DefaultQueryMappingConfiguration();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,7 +40,7 @@ import org.springframework.data.jdbc.core.convert.InsertStrategyFactory;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcConverter;
|
||||
import org.springframework.data.jdbc.core.convert.SqlGeneratorSource;
|
||||
import org.springframework.data.jdbc.core.convert.SqlParametersFactory;
|
||||
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactoryBean;
|
||||
import org.springframework.data.jdbc.testing.IntegrationTest;
|
||||
import org.springframework.data.jdbc.testing.TestConfiguration;
|
||||
@@ -62,6 +62,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* @author Fei Dong
|
||||
* @author Chirag Tailor
|
||||
* @author Diego Krupitza
|
||||
* @author Mikhail Polivakha
|
||||
*/
|
||||
@IntegrationTest
|
||||
public class EnableJdbcRepositoriesIntegrationTests {
|
||||
@@ -168,7 +169,7 @@ public class EnableJdbcRepositoriesIntegrationTests {
|
||||
RelationalMappingContext context, JdbcConverter converter, Dialect dialect) {
|
||||
return new DataAccessStrategyFactory(new SqlGeneratorSource(context, converter, dialect), converter, template,
|
||||
new SqlParametersFactory(context, converter),
|
||||
new InsertStrategyFactory(template, dialect)).create();
|
||||
new InsertStrategyFactory(template, dialect), QueryMappingConfiguration.EMPTY).create();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcConverter;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcH2Dialect;
|
||||
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.repository.config.DefaultQueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.repository.query.Query;
|
||||
import org.springframework.data.mapping.callback.EntityCallbacks;
|
||||
|
||||
@@ -38,7 +38,7 @@ import org.springframework.data.jdbc.core.convert.DataAccessStrategy;
|
||||
import org.springframework.data.jdbc.core.convert.DefaultDataAccessStrategy;
|
||||
import org.springframework.data.jdbc.core.convert.MappingJdbcConverter;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
|
||||
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
|
||||
import org.springframework.data.relational.core.dialect.Dialect;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.springframework.data.jdbc.core.dialect.JdbcArrayColumns;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcDialect;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcSimpleTypes;
|
||||
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
|
||||
import org.springframework.data.jdbc.repository.config.DialectResolver;
|
||||
import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory;
|
||||
import org.springframework.data.mapping.callback.EntityCallback;
|
||||
@@ -118,10 +119,10 @@ public class TestConfiguration {
|
||||
@Bean
|
||||
DataAccessStrategy defaultDataAccessStrategy(
|
||||
@Qualifier("namedParameterJdbcTemplate") NamedParameterJdbcOperations template, RelationalMappingContext context,
|
||||
JdbcConverter converter, Dialect dialect) {
|
||||
JdbcConverter converter, Dialect dialect, Optional<QueryMappingConfiguration> queryMappingConfiguration) {
|
||||
|
||||
return new DataAccessStrategyFactory(new SqlGeneratorSource(context, converter, dialect), converter, template,
|
||||
new SqlParametersFactory(context, converter), new InsertStrategyFactory(template, dialect)).create();
|
||||
new SqlParametersFactory(context, converter), new InsertStrategyFactory(template, dialect), queryMappingConfiguration.orElse(QueryMappingConfiguration.EMPTY)).create();
|
||||
}
|
||||
|
||||
@Bean("jdbcMappingContext")
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
DROP TABLE car;
|
||||
|
||||
CREATE TABLE car ( id BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) PRIMARY KEY, model VARCHAR(100));
|
||||
@@ -0,0 +1,4 @@
|
||||
DROP TABLE car;
|
||||
|
||||
|
||||
CREATE TABLE car ( id BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) PRIMARY KEY, model VARCHAR(100));
|
||||
@@ -0,0 +1 @@
|
||||
CREATE TABLE car ( id BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) PRIMARY KEY, model VARCHAR(100));
|
||||
@@ -0,0 +1 @@
|
||||
CREATE TABLE car ( id INT NOT NULL AUTO_INCREMENT, model VARCHAR(100), PRIMARY KEY (id));
|
||||
@@ -0,0 +1,2 @@
|
||||
DROP TABLE IF EXISTS car;
|
||||
CREATE TABLE car ( id int IDENTITY(1,1) PRIMARY KEY, model VARCHAR(100));
|
||||
@@ -0,0 +1 @@
|
||||
CREATE TABLE car ( id INT NOT NULL AUTO_INCREMENT, model VARCHAR(100), PRIMARY KEY (id));
|
||||
@@ -0,0 +1,2 @@
|
||||
DROP TABLE CAR;
|
||||
CREATE TABLE CAR ( id NUMBER GENERATED by default on null as IDENTITY PRIMARY KEY, model VARCHAR(100));
|
||||
@@ -0,0 +1,2 @@
|
||||
DROP TABLE car;
|
||||
CREATE TABLE car ( id SERIAL PRIMARY KEY, model VARCHAR(100));
|
||||
Reference in New Issue
Block a user