Skip to content

Commit a481a59

Browse files
committed
GH-1006 included QueryMappingConfiguration for all part tree queries
1 parent 25effcd commit a481a59

20 files changed

+212
-30
lines changed

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DataAccessStrategyFactory.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.jdbc.core.convert;
1717

18+
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
1819
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
1920
import org.springframework.util.Assert;
2021

@@ -25,6 +26,7 @@
2526
* {@link DataAccessStrategy} for consistent access strategy creation.
2627
*
2728
* @author Mark Paluch
29+
* @author Mikhail Polivakha
2830
* @since 3.2
2931
*/
3032
public class DataAccessStrategyFactory {
@@ -34,6 +36,7 @@ public class DataAccessStrategyFactory {
3436
private final NamedParameterJdbcOperations operations;
3537
private final SqlParametersFactory sqlParametersFactory;
3638
private final InsertStrategyFactory insertStrategyFactory;
39+
private final QueryMappingConfiguration queryMappingConfiguration;
3740

3841
/**
3942
* Creates a new {@link DataAccessStrategyFactory}.
@@ -46,7 +49,7 @@ public class DataAccessStrategyFactory {
4649
*/
4750
public DataAccessStrategyFactory(SqlGeneratorSource sqlGeneratorSource, JdbcConverter converter,
4851
NamedParameterJdbcOperations operations, SqlParametersFactory sqlParametersFactory,
49-
InsertStrategyFactory insertStrategyFactory) {
52+
InsertStrategyFactory insertStrategyFactory, QueryMappingConfiguration queryMappingConfiguration) {
5053

5154
Assert.notNull(sqlGeneratorSource, "SqlGeneratorSource must not be null");
5255
Assert.notNull(converter, "JdbcConverter must not be null");
@@ -59,6 +62,7 @@ public DataAccessStrategyFactory(SqlGeneratorSource sqlGeneratorSource, JdbcConv
5962
this.operations = operations;
6063
this.sqlParametersFactory = sqlParametersFactory;
6164
this.insertStrategyFactory = insertStrategyFactory;
65+
this.queryMappingConfiguration = queryMappingConfiguration;
6266
}
6367

6468
/**
@@ -70,7 +74,7 @@ public DataAccessStrategy create() {
7074

7175
DefaultDataAccessStrategy defaultDataAccessStrategy = new DefaultDataAccessStrategy(sqlGeneratorSource,
7276
this.converter.getMappingContext(), this.converter, this.operations, sqlParametersFactory,
73-
insertStrategyFactory);
77+
insertStrategyFactory, queryMappingConfiguration);
7478

7579
if (this.converter.getMappingContext().isSingleQueryLoadingEnabled()) {
7680
return new SingleQueryFallbackDataAccessStrategy(sqlGeneratorSource, converter, operations,

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultDataAccessStrategy.java

+22-10
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.dao.OptimisticLockingFailureException;
2828
import org.springframework.data.domain.Pageable;
2929
import org.springframework.data.domain.Sort;
30+
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
3031
import org.springframework.data.mapping.PersistentPropertyPath;
3132
import org.springframework.data.relational.core.conversion.IdValueSource;
3233
import org.springframework.data.relational.core.mapping.AggregatePath;
@@ -60,6 +61,7 @@
6061
* @author Radim Tlusty
6162
* @author Chirag Tailor
6263
* @author Diego Krupitza
64+
* @author Mikhail Polivakha
6365
* @since 1.1
6466
*/
6567
public class DefaultDataAccessStrategy implements DataAccessStrategy {
@@ -71,6 +73,8 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
7173
private final SqlParametersFactory sqlParametersFactory;
7274
private final InsertStrategyFactory insertStrategyFactory;
7375

76+
private final QueryMappingConfiguration queryMappingConfiguration;
77+
7478
/**
7579
* Creates a {@link DefaultDataAccessStrategy}
7680
*
@@ -82,21 +86,23 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
8286
*/
8387
public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, RelationalMappingContext context,
8488
JdbcConverter converter, NamedParameterJdbcOperations operations, SqlParametersFactory sqlParametersFactory,
85-
InsertStrategyFactory insertStrategyFactory) {
89+
InsertStrategyFactory insertStrategyFactory, QueryMappingConfiguration queryMappingConfiguration) {
8690

8791
Assert.notNull(sqlGeneratorSource, "SqlGeneratorSource must not be null");
8892
Assert.notNull(context, "RelationalMappingContext must not be null");
8993
Assert.notNull(converter, "JdbcConverter must not be null");
9094
Assert.notNull(operations, "NamedParameterJdbcOperations must not be null");
9195
Assert.notNull(sqlParametersFactory, "SqlParametersFactory must not be null");
9296
Assert.notNull(insertStrategyFactory, "InsertStrategyFactory must not be null");
97+
Assert.notNull(queryMappingConfiguration, "InsertStrategyFactory must not be null");
9398

9499
this.sqlGeneratorSource = sqlGeneratorSource;
95100
this.context = context;
96101
this.converter = converter;
97102
this.operations = operations;
98103
this.sqlParametersFactory = sqlParametersFactory;
99104
this.insertStrategyFactory = insertStrategyFactory;
105+
this.queryMappingConfiguration = queryMappingConfiguration;
100106
}
101107

102108
@Override
@@ -265,15 +271,15 @@ public <T> T findById(Object id, Class<T> domainType) {
265271
SqlIdentifierParameterSource parameter = sqlParametersFactory.forQueryById(id, domainType, ID_SQL_PARAMETER);
266272

267273
try {
268-
return operations.queryForObject(findOneSql, parameter, getEntityRowMapper(domainType));
274+
return operations.queryForObject(findOneSql, parameter, getRowMapper(domainType));
269275
} catch (EmptyResultDataAccessException e) {
270276
return null;
271277
}
272278
}
273279

274280
@Override
275281
public <T> Iterable<T> findAll(Class<T> domainType) {
276-
return operations.query(sql(domainType).getFindAll(), getEntityRowMapper(domainType));
282+
return operations.query(sql(domainType).getFindAll(), getRowMapper(domainType));
277283
}
278284

279285
@Override
@@ -285,7 +291,7 @@ public <T> Iterable<T> findAllById(Iterable<?> ids, Class<T> domainType) {
285291

286292
SqlParameterSource parameterSource = sqlParametersFactory.forQueryByIds(ids, domainType);
287293
String findAllInListSql = sql(domainType).getFindAllInList();
288-
return operations.query(findAllInListSql, parameterSource, getEntityRowMapper(domainType));
294+
return operations.query(findAllInListSql, parameterSource, getRowMapper(domainType));
289295
}
290296

291297
@Override
@@ -339,12 +345,12 @@ public <T> boolean existsById(Object id, Class<T> domainType) {
339345

340346
@Override
341347
public <T> Iterable<T> findAll(Class<T> domainType, Sort sort) {
342-
return operations.query(sql(domainType).getFindAll(sort), getEntityRowMapper(domainType));
348+
return operations.query(sql(domainType).getFindAll(sort), getRowMapper(domainType));
343349
}
344350

345351
@Override
346352
public <T> Iterable<T> findAll(Class<T> domainType, Pageable pageable) {
347-
return operations.query(sql(domainType).getFindAll(pageable), getEntityRowMapper(domainType));
353+
return operations.query(sql(domainType).getFindAll(pageable), getRowMapper(domainType));
348354
}
349355

350356
@Override
@@ -354,7 +360,7 @@ public <T> Optional<T> findOne(Query query, Class<T> domainType) {
354360
String sqlQuery = sql(domainType).selectByQuery(query, parameterSource);
355361

356362
try {
357-
return Optional.ofNullable(operations.queryForObject(sqlQuery, parameterSource, getEntityRowMapper(domainType)));
363+
return Optional.ofNullable(operations.queryForObject(sqlQuery, parameterSource, getRowMapper(domainType)));
358364
} catch (EmptyResultDataAccessException e) {
359365
return Optional.empty();
360366
}
@@ -366,7 +372,7 @@ public <T> Iterable<T> findAll(Query query, Class<T> domainType) {
366372
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
367373
String sqlQuery = sql(domainType).selectByQuery(query, parameterSource);
368374

369-
return operations.query(sqlQuery, parameterSource, getEntityRowMapper(domainType));
375+
return operations.query(sqlQuery, parameterSource, getRowMapper(domainType));
370376
}
371377

372378
@Override
@@ -375,7 +381,7 @@ public <T> Iterable<T> findAll(Query query, Class<T> domainType, Pageable pageab
375381
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
376382
String sqlQuery = sql(domainType).selectByQuery(query, parameterSource, pageable);
377383

378-
return operations.query(sqlQuery, parameterSource, getEntityRowMapper(domainType));
384+
return operations.query(sqlQuery, parameterSource, getRowMapper(domainType));
379385
}
380386

381387
@Override
@@ -404,7 +410,13 @@ public <T> long count(Query query, Class<T> domainType) {
404410
return result;
405411
}
406412

407-
private <T> EntityRowMapper<T> getEntityRowMapper(Class<T> domainType) {
413+
private <T> RowMapper<? extends T> getRowMapper(Class<T> domainType) {
414+
RowMapper<? extends T> targetRowMapper;
415+
416+
if ((targetRowMapper = queryMappingConfiguration.getRowMapper(domainType)) != null) {
417+
return targetRowMapper;
418+
}
419+
408420
return new EntityRowMapper<>(getRequiredPersistentEntity(domainType), converter);
409421
}
410422

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/mybatis/MyBatisDataAccessStrategy.java

+7-4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.springframework.data.domain.Pageable;
3030
import org.springframework.data.domain.Sort;
3131
import org.springframework.data.jdbc.core.convert.*;
32+
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
3233
import org.springframework.data.mapping.PersistentPropertyPath;
3334
import org.springframework.data.mapping.PropertyPath;
3435
import org.springframework.data.relational.core.conversion.IdValueSource;
@@ -72,9 +73,10 @@ public class MyBatisDataAccessStrategy implements DataAccessStrategy {
7273
* uses a {@link DefaultDataAccessStrategy}
7374
*/
7475
public static DataAccessStrategy createCombinedAccessStrategy(RelationalMappingContext context,
75-
JdbcConverter converter, NamedParameterJdbcOperations operations, SqlSession sqlSession, Dialect dialect) {
76+
JdbcConverter converter, NamedParameterJdbcOperations operations, SqlSession sqlSession,
77+
Dialect dialect, QueryMappingConfiguration queryMappingConfiguration) {
7678
return createCombinedAccessStrategy(context, converter, operations, sqlSession, NamespaceStrategy.DEFAULT_INSTANCE,
77-
dialect);
79+
dialect, queryMappingConfiguration);
7880
}
7981

8082
/**
@@ -83,7 +85,7 @@ public static DataAccessStrategy createCombinedAccessStrategy(RelationalMappingC
8385
*/
8486
public static DataAccessStrategy createCombinedAccessStrategy(RelationalMappingContext context,
8587
JdbcConverter converter, NamedParameterJdbcOperations operations, SqlSession sqlSession,
86-
NamespaceStrategy namespaceStrategy, Dialect dialect) {
88+
NamespaceStrategy namespaceStrategy, Dialect dialect, QueryMappingConfiguration queryMappingConfiguration) {
8789

8890
SqlGeneratorSource sqlGeneratorSource = new SqlGeneratorSource(context, converter, dialect);
8991
SqlParametersFactory sqlParametersFactory = new SqlParametersFactory(context, converter);
@@ -94,7 +96,8 @@ public static DataAccessStrategy createCombinedAccessStrategy(RelationalMappingC
9496
converter, //
9597
operations, //
9698
sqlParametersFactory, //
97-
insertStrategyFactory //
99+
insertStrategyFactory, //
100+
queryMappingConfiguration //
98101
).create();
99102

100103
// the DefaultDataAccessStrategy needs a reference to the returned DataAccessStrategy. This creates a dependency

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.springframework.data.jdbc.core.dialect.JdbcDialect;
4141
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
4242
import org.springframework.data.jdbc.core.mapping.JdbcSimpleTypes;
43+
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
4344
import org.springframework.data.mapping.model.SimpleTypeHolder;
4445
import org.springframework.data.relational.RelationalManagedTypes;
4546
import org.springframework.data.relational.core.conversion.RelationalConverter;
@@ -61,6 +62,7 @@
6162
* @author Christoph Strobl
6263
* @author Myeonghyeon Lee
6364
* @author Chirag Tailor
65+
* @author Mikhail Polivakha
6466
* @since 1.1
6567
*/
6668
@Configuration(proxyBeanMethods = false)
@@ -70,6 +72,8 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware {
7072

7173
private ApplicationContext applicationContext;
7274

75+
private QueryMappingConfiguration queryMappingConfiguration;
76+
7377
/**
7478
* Returns the base packages to scan for JDBC mapped entities at startup. Returns the package name of the
7579
* configuration class' (the concrete class, not this one here) by default. So if you have a
@@ -208,7 +212,9 @@ public DataAccessStrategy dataAccessStrategyBean(NamedParameterJdbcOperations op
208212
SqlGeneratorSource sqlGeneratorSource = new SqlGeneratorSource(context, jdbcConverter, dialect);
209213
DataAccessStrategyFactory factory = new DataAccessStrategyFactory(sqlGeneratorSource, jdbcConverter, operations,
210214
new SqlParametersFactory(context, jdbcConverter),
211-
new InsertStrategyFactory(operations, dialect));
215+
new InsertStrategyFactory(operations, dialect),
216+
this.queryMappingConfiguration
217+
);
212218

213219
return factory.create();
214220
}
@@ -232,6 +238,10 @@ public void setApplicationContext(ApplicationContext applicationContext) throws
232238
this.applicationContext = applicationContext;
233239
}
234240

241+
public void setQueryMappingConfiguration(Optional<QueryMappingConfiguration> queryMappingConfiguration) throws BeansException {
242+
this.queryMappingConfiguration = queryMappingConfiguration.orElse(QueryMappingConfiguration.EMPTY);
243+
}
244+
235245
/**
236246
* Scans the mapping base package for classes annotated with {@link Table}. By default, it scans for entities in all
237247
* packages returned by {@link #getMappingBasePackages()}.

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/MyBatisJdbcConfiguration.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.springframework.data.jdbc.repository.config;
1717

18+
import java.util.Optional;
19+
1820
import org.apache.ibatis.session.SqlSession;
1921
import org.springframework.beans.factory.annotation.Autowired;
2022
import org.springframework.context.annotation.Bean;
@@ -23,25 +25,29 @@
2325
import org.springframework.data.jdbc.core.convert.JdbcConverter;
2426
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
2527
import org.springframework.data.jdbc.mybatis.MyBatisDataAccessStrategy;
28+
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
2629
import org.springframework.data.relational.core.dialect.Dialect;
2730
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
2831

2932
/**
3033
* Configuration class tweaking Spring Data JDBC to use a {@link MyBatisDataAccessStrategy} instead of the default one.
3134
*
3235
* @author Oliver Drotbohm
36+
* @author Mikhail Polivakha
3337
* @since 1.1
3438
*/
3539
@Configuration(proxyBeanMethods = false)
3640
public class MyBatisJdbcConfiguration extends AbstractJdbcConfiguration {
3741

3842
private @Autowired SqlSession session;
3943

44+
private @Autowired Optional<QueryMappingConfiguration> queryMappingConfiguration;
45+
4046
@Bean
4147
@Override
4248
public DataAccessStrategy dataAccessStrategyBean(NamedParameterJdbcOperations operations, JdbcConverter jdbcConverter,
4349
JdbcMappingContext context, Dialect dialect) {
4450

45-
return MyBatisDataAccessStrategy.createCombinedAccessStrategy(context, jdbcConverter, operations, session, dialect);
51+
return MyBatisDataAccessStrategy.createCombinedAccessStrategy(context, jdbcConverter, operations, session, dialect, queryMappingConfiguration.orElse(QueryMappingConfiguration.EMPTY));
4652
}
4753
}

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
* @author Mark Paluch
4949
* @author Hebert Coelho
5050
* @author Chirag Tailor
51+
* @author Mikhail Polivakha
5152
*/
5253
public class JdbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
5354
extends TransactionalRepositoryFactoryBeanSupport<T, S, ID> implements ApplicationEventPublisherAware {
@@ -161,11 +162,15 @@ public void afterPropertiesSet() {
161162

162163
if (this.operations == null) {
163164

164-
Assert.state(beanFactory != null, "If no JdbcOperations are set a BeanFactory must be available");
165+
Assert.state( beanFactory != null, "If no JdbcOperations are set a BeanFactory must be available");
165166

166167
this.operations = beanFactory.getBean(NamedParameterJdbcOperations.class);
167168
}
168169

170+
if (this.queryMappingConfiguration == null) {
171+
this.queryMappingConfiguration = QueryMappingConfiguration.EMPTY;
172+
}
173+
169174
if (this.dataAccessStrategy == null) {
170175

171176
Assert.state(beanFactory != null, "If no DataAccessStrategy is set a BeanFactory must be available");
@@ -181,16 +186,12 @@ public void afterPropertiesSet() {
181186
InsertStrategyFactory insertStrategyFactory = new InsertStrategyFactory(this.operations, this.dialect);
182187

183188
DataAccessStrategyFactory factory = new DataAccessStrategyFactory(sqlGeneratorSource, this.converter,
184-
this.operations, sqlParametersFactory, insertStrategyFactory);
189+
this.operations, sqlParametersFactory, insertStrategyFactory, queryMappingConfiguration);
185190

186191
return factory.create();
187192
});
188193
}
189194

190-
if (this.queryMappingConfiguration == null) {
191-
this.queryMappingConfiguration = QueryMappingConfiguration.EMPTY;
192-
}
193-
194195
if (beanFactory != null) {
195196
entityCallbacks = EntityCallbacks.create(beanFactory);
196197
}

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/DefaultDataAccessStrategyUnitTests.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.junit.jupiter.api.Test;
2424
import org.springframework.data.annotation.Id;
2525
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
26+
import org.springframework.data.jdbc.repository.QueryMappingConfiguration;
2627
import org.springframework.data.relational.core.conversion.IdValueSource;
2728
import org.springframework.data.relational.core.dialect.Dialect;
2829
import org.springframework.data.relational.core.dialect.HsqlDbDialect;
@@ -40,6 +41,7 @@
4041
* @author Myat Min
4142
* @author Radim Tlusty
4243
* @author Chirag Tailor
44+
* @author Mikhail Polivakha
4345
*/
4446
class DefaultDataAccessStrategyUnitTests {
4547

@@ -66,7 +68,8 @@ void before() {
6668
converter, //
6769
namedJdbcOperations, //
6870
sqlParametersFactory, //
69-
insertStrategyFactory).create();
71+
insertStrategyFactory,
72+
QueryMappingConfiguration.EMPTY).create();
7073

7174
relationResolver.setDelegate(accessStrategy);
7275

0 commit comments

Comments
 (0)