diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/JdbcQueryMethod.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/JdbcQueryMethod.java index d62f6534..6d22d1b5 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/JdbcQueryMethod.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/JdbcQueryMethod.java @@ -163,7 +163,7 @@ public class JdbcQueryMethod extends QueryMethod { return StringUtils.hasText(annotatedName) ? annotatedName : getNamedQueryName(); } - /* + /** * Returns the class to be used as {@link org.springframework.jdbc.core.RowMapper} * * @return May be {@code null}. @@ -173,6 +173,17 @@ public class JdbcQueryMethod extends QueryMethod { return getMergedAnnotationAttribute("rowMapperClass"); } + + /** + * Returns the bean to be used as {@link org.springframework.jdbc.core.RowMapper} + * + * @return May be {@code null}. + */ + @Nullable + String getRowMapperBean() { + return getMergedAnnotationAttribute("rowMapperBean"); + } + /** * Returns the class to be used as {@link org.springframework.jdbc.core.ResultSetExtractor} * @@ -183,6 +194,16 @@ public class JdbcQueryMethod extends QueryMethod { return getMergedAnnotationAttribute("resultSetExtractorClass"); } + /** + * Returns the bean to be used as {@link org.springframework.jdbc.core.ResultSetExtractor} + * + * @return May be {@code null}. + */ + @Nullable + String getResultSetExtractorBean() { + return getMergedAnnotationAttribute("resultSetExtractorBean"); + } + /** * Returns whether the query method is a modifying one. * diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/Query.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/Query.java index a97c9f67..ad170770 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/Query.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/Query.java @@ -56,9 +56,21 @@ public @interface Query { */ Class rowMapperClass() default RowMapper.class; + /** + * Optional bean of type {@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. + */ + String rowMapperBean() default "RowMapper"; + /** * 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 resultSetExtractorClass() default ResultSetExtractor.class; + + /** + * Optional bean of type {@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. + */ + String resultSetExtractorBean() default "ResultSetExtractor"; } diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQuery.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQuery.java index e6b6b456..5db1bc24 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQuery.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQuery.java @@ -19,6 +19,7 @@ import java.lang.reflect.Constructor; import java.sql.JDBCType; import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.BeanFactory; import org.springframework.data.jdbc.core.convert.JdbcColumnTypes; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.core.convert.JdbcValue; @@ -51,6 +52,7 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery { private final JdbcQueryMethod queryMethod; private final JdbcQueryExecution executor; private final JdbcConverter converter; + private BeanFactory beanfactory; /** * Creates a new {@link StringBasedJdbcQuery} for the given {@link JdbcQueryMethod}, {@link RelationalMappingContext} @@ -61,12 +63,13 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery { * @param defaultRowMapper can be {@literal null} (only in case of a modifying query). */ public StringBasedJdbcQuery(JdbcQueryMethod queryMethod, NamedParameterJdbcOperations operations, - @Nullable RowMapper defaultRowMapper, JdbcConverter converter) { + @Nullable RowMapper defaultRowMapper, JdbcConverter converter, BeanFactory beanfactory) { super(queryMethod, operations, defaultRowMapper); this.queryMethod = queryMethod; this.converter = converter; + this.beanfactory = beanfactory; RowMapper rowMapper = determineRowMapper(defaultRowMapper); executor = getQueryExecution( // @@ -137,6 +140,11 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery { @Nullable @SuppressWarnings({ "rawtypes", "unchecked" }) ResultSetExtractor determineResultSetExtractor(@Nullable RowMapper rowMapper) { + String resultSetExtractorBean = queryMethod.getResultSetExtractorBean(); + + if (resultSetExtractorBean != null && !"ResultSetExtractor".equals(resultSetExtractorBean)) { + return (ResultSetExtractor) beanfactory.getBean(resultSetExtractorBean); + } Class resultSetExtractorClass = queryMethod.getResultSetExtractorClass(); @@ -157,6 +165,12 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery { @SuppressWarnings("unchecked") RowMapper determineRowMapper(@Nullable RowMapper defaultMapper) { + String rowMapperBean = queryMethod.getRowMapperBean(); + + if (rowMapperBean != null && !"RowMapper".equals(rowMapperBean)) { + return (RowMapper) beanfactory.getBean(rowMapperBean); + } + Class rowMapperClass = queryMethod.getRowMapperClass(); if (isUnconfigured(rowMapperClass, RowMapper.class)) { diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java index 6c8ac595..9f655915 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java @@ -19,6 +19,7 @@ import java.lang.reflect.Method; import java.sql.ResultSet; import java.sql.SQLException; +import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.jdbc.core.convert.EntityRowMapper; import org.springframework.data.jdbc.core.convert.JdbcConverter; @@ -63,10 +64,12 @@ class JdbcQueryLookupStrategy implements QueryLookupStrategy { private final Dialect dialect; private final QueryMappingConfiguration queryMappingConfiguration; private final NamedParameterJdbcOperations operations; + private BeanFactory beanfactory; public JdbcQueryLookupStrategy(ApplicationEventPublisher publisher, @Nullable EntityCallbacks callbacks, RelationalMappingContext context, JdbcConverter converter, Dialect dialect, - QueryMappingConfiguration queryMappingConfiguration, NamedParameterJdbcOperations operations) { + QueryMappingConfiguration queryMappingConfiguration, NamedParameterJdbcOperations operations, + BeanFactory beanfactory) { Assert.notNull(publisher, "ApplicationEventPublisher must not be null"); Assert.notNull(context, "RelationalMappingContextPublisher must not be null"); @@ -82,6 +85,7 @@ class JdbcQueryLookupStrategy implements QueryLookupStrategy { this.dialect = dialect; this.queryMappingConfiguration = queryMappingConfiguration; this.operations = operations; + this.beanfactory = beanfactory; } /* @@ -99,7 +103,7 @@ class JdbcQueryLookupStrategy implements QueryLookupStrategy { if (namedQueries.hasQuery(queryMethod.getNamedQueryName()) || queryMethod.hasAnnotatedQuery()) { RowMapper mapper = queryMethod.isModifyingQuery() ? null : createMapper(queryMethod); - return new StringBasedJdbcQuery(queryMethod, operations, mapper, converter); + return new StringBasedJdbcQuery(queryMethod, operations, mapper, converter, beanfactory); } else { return new PartTreeJdbcQuery(context, queryMethod, dialect, converter, operations, createMapper(queryMethod)); } diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactory.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactory.java index 248efc3c..363f5d2a 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactory.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactory.java @@ -17,6 +17,7 @@ package org.springframework.data.jdbc.repository.support; import java.util.Optional; +import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.jdbc.core.JdbcAggregateTemplate; import org.springframework.data.jdbc.core.convert.DataAccessStrategy; @@ -53,6 +54,7 @@ public class JdbcRepositoryFactory extends RepositoryFactorySupport { private final DataAccessStrategy accessStrategy; private final NamedParameterJdbcOperations operations; private final Dialect dialect; + private BeanFactory beanfactory; private QueryMappingConfiguration queryMappingConfiguration = QueryMappingConfiguration.EMPTY; private EntityCallbacks entityCallbacks; @@ -70,7 +72,7 @@ public class JdbcRepositoryFactory extends RepositoryFactorySupport { */ public JdbcRepositoryFactory(DataAccessStrategy dataAccessStrategy, RelationalMappingContext context, JdbcConverter converter, Dialect dialect, ApplicationEventPublisher publisher, - NamedParameterJdbcOperations operations) { + NamedParameterJdbcOperations operations, BeanFactory beanfactory) { Assert.notNull(dataAccessStrategy, "DataAccessStrategy must not be null!"); Assert.notNull(context, "RelationalMappingContext must not be null!"); @@ -84,6 +86,7 @@ public class JdbcRepositoryFactory extends RepositoryFactorySupport { this.dialect = dialect; this.accessStrategy = dataAccessStrategy; this.operations = operations; + this.beanfactory = beanfactory; } /** @@ -142,7 +145,7 @@ public class JdbcRepositoryFactory extends RepositoryFactorySupport { QueryMethodEvaluationContextProvider evaluationContextProvider) { return Optional.of(new JdbcQueryLookupStrategy(publisher, entityCallbacks, context, converter, dialect, - queryMappingConfiguration, operations)); + queryMappingConfiguration, operations, beanfactory)); } /** diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java index b5e4eb82..22de2f3e 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java @@ -86,7 +86,7 @@ public class JdbcRepositoryFactoryBean, S, ID extend protected RepositoryFactorySupport doCreateRepositoryFactory() { JdbcRepositoryFactory jdbcRepositoryFactory = new JdbcRepositoryFactory(dataAccessStrategy, mappingContext, - converter, dialect, publisher, operations); + converter, dialect, publisher, operations, beanFactory); jdbcRepositoryFactory.setQueryMappingConfiguration(queryMappingConfiguration); jdbcRepositoryFactory.setEntityCallbacks(entityCallbacks); diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/SimpleJdbcRepositoryEventsUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/SimpleJdbcRepositoryEventsUnitTests.java index 42bf4811..f3eac239 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/SimpleJdbcRepositoryEventsUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/SimpleJdbcRepositoryEventsUnitTests.java @@ -32,6 +32,7 @@ import org.assertj.core.groups.Tuple; import org.junit.Before; import org.junit.Test; import org.mockito.stubbing.Answer; +import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.annotation.Id; import org.springframework.data.domain.PageRequest; @@ -82,6 +83,7 @@ public class SimpleJdbcRepositoryEventsUnitTests { DummyEntityRepository repository; DefaultDataAccessStrategy dataAccessStrategy; + BeanFactory beanFactory = mock(BeanFactory.class); @Before public void before() { @@ -99,7 +101,7 @@ public class SimpleJdbcRepositoryEventsUnitTests { doReturn(true).when(dataAccessStrategy).update(any(), any()); JdbcRepositoryFactory factory = new JdbcRepositoryFactory(dataAccessStrategy, context, converter, - H2Dialect.INSTANCE, publisher, operations); + H2Dialect.INSTANCE, publisher, operations, beanFactory); this.repository = factory.getRepository(DummyEntityRepository.class); } diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/StringBasedJdbcQueryMappingConfigurationIntegrationTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/StringBasedJdbcQueryMappingConfigurationIntegrationTests.java index 476888c4..0ba3e2e7 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/StringBasedJdbcQueryMappingConfigurationIntegrationTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/StringBasedJdbcQueryMappingConfigurationIntegrationTests.java @@ -15,10 +15,8 @@ */ package org.springframework.data.jdbc.repository; -import static org.assertj.core.api.Assertions.*; - -import lombok.AllArgsConstructor; -import lombok.Data; +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.data.jdbc.testing.SingleBaseMappingTestConfiguration.VALUE_PROCESSED_BY_SERVICE; import java.sql.ResultSet; import java.sql.SQLException; @@ -33,10 +31,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.dao.DataAccessException; -import org.springframework.data.annotation.Id; import org.springframework.data.jdbc.repository.config.DefaultQueryMappingConfiguration; import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories; import org.springframework.data.jdbc.repository.query.Query; +import org.springframework.data.jdbc.testing.SingleBaseMappingTestConfiguration.Car; import org.springframework.data.jdbc.testing.TestConfiguration; import org.springframework.data.repository.CrudRepository; import org.springframework.jdbc.core.ResultSetExtractor; @@ -55,7 +53,7 @@ import org.springframework.transaction.annotation.Transactional; @Transactional public class StringBasedJdbcQueryMappingConfigurationIntegrationTests { - private static String CAR_MODEL = "ResultSetExtractor Car"; + private final static String CAR_MODEL = "ResultSetExtractor Car"; @Configuration @Import(TestConfiguration.class) @@ -89,18 +87,22 @@ public class StringBasedJdbcQueryMappingConfigurationIntegrationTests { assertThat(cars).allMatch(car -> CAR_MODEL.equals(car.getModel())); } - interface CarRepository extends CrudRepository { + @Test // DATAJDBC-430 + public void customFindWithRowMapperSupportingInjection() { + carRepository.save(new Car(null, "Some model")); + List names = carRepository.findByNameWithRowMapperBean(); - @Query(value = "select * from car", resultSetExtractorClass = CarResultSetExtractor.class) - List customFindAll(); + assertThat(names).hasSize(1); + assertThat(names).allMatch(name -> VALUE_PROCESSED_BY_SERVICE.equals(name)); } - @Data - @AllArgsConstructor - static class Car { + @Test // DATAJDBC-430 + public void customFindWithResultSetExtractorSupportingInjection() { + carRepository.save(new Car(null, "Some model")); + Iterable cars = carRepository.findByNameWithResultSetExtractor(); - @Id private Long id; - private String model; + assertThat(cars).hasSize(1); + assertThat(cars).allMatch(car -> VALUE_PROCESSED_BY_SERVICE.equals(car.getModel())); } static class CarResultSetExtractor implements ResultSetExtractor> { @@ -109,6 +111,16 @@ public class StringBasedJdbcQueryMappingConfigurationIntegrationTests { public List extractData(ResultSet rs) throws SQLException, DataAccessException { return Arrays.asList(new Car(1L, CAR_MODEL)); } + } + private interface CarRepository extends CrudRepository { + @Query(value = "select * from car", resultSetExtractorClass = CarResultSetExtractor.class) + List customFindAll(); + + @Query(value = "select * from car", resultSetExtractorBean = "CarResultSetExtractorBean") + List findByNameWithResultSetExtractor(); + + @Query(value = "select model from car", rowMapperBean = "CustomRowMapperBean") + List findByNameWithRowMapperBean(); } } diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQueryUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQueryUnitTests.java index bf7f952b..b9ef96e8 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQueryUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQueryUnitTests.java @@ -24,6 +24,7 @@ import org.assertj.core.api.Assertions; import org.junit.Before; import org.junit.Test; +import org.springframework.beans.factory.BeanFactory; import org.springframework.dao.DataAccessException; import org.springframework.data.jdbc.core.convert.BasicJdbcConverter; import org.springframework.data.jdbc.core.convert.JdbcConverter; @@ -53,6 +54,7 @@ public class StringBasedJdbcQueryUnitTests { NamedParameterJdbcOperations operations; RelationalMappingContext context; JdbcConverter converter; + BeanFactory beanFactory; @Before public void setup() throws NoSuchMethodException { @@ -67,6 +69,7 @@ public class StringBasedJdbcQueryUnitTests { this.operations = mock(NamedParameterJdbcOperations.class); this.context = mock(RelationalMappingContext.class, RETURNS_DEEP_STUBS); this.converter = new BasicJdbcConverter(context, mock(RelationResolver.class)); + this.beanFactory = mock(BeanFactory.class); } @Test // DATAJDBC-165 @@ -75,7 +78,7 @@ public class StringBasedJdbcQueryUnitTests { doReturn(null).when(queryMethod).getDeclaredQuery(); Assertions.assertThatExceptionOfType(IllegalStateException.class) // - .isThrownBy(() -> new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter) + .isThrownBy(() -> new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter, beanFactory) .execute(new Object[] {})); } @@ -84,7 +87,7 @@ public class StringBasedJdbcQueryUnitTests { doReturn("some sql statement").when(queryMethod).getDeclaredQuery(); doReturn(RowMapper.class).when(queryMethod).getRowMapperClass(); - StringBasedJdbcQuery query = new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter); + StringBasedJdbcQuery query = new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter, beanFactory); assertThat(query.determineRowMapper(defaultRowMapper)).isEqualTo(defaultRowMapper); } @@ -93,7 +96,7 @@ public class StringBasedJdbcQueryUnitTests { public void defaultRowMapperIsUsedForNull() { doReturn("some sql statement").when(queryMethod).getDeclaredQuery(); - StringBasedJdbcQuery query = new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter); + StringBasedJdbcQuery query = new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter, beanFactory); assertThat(query.determineRowMapper(defaultRowMapper)).isEqualTo(defaultRowMapper); } @@ -104,7 +107,7 @@ public class StringBasedJdbcQueryUnitTests { doReturn("some sql statement").when(queryMethod).getDeclaredQuery(); doReturn(CustomRowMapper.class).when(queryMethod).getRowMapperClass(); - StringBasedJdbcQuery query = new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter); + StringBasedJdbcQuery query = new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter, beanFactory); assertThat(query.determineRowMapper(defaultRowMapper)).isInstanceOf(CustomRowMapper.class); } @@ -115,9 +118,9 @@ public class StringBasedJdbcQueryUnitTests { doReturn("some sql statement").when(queryMethod).getDeclaredQuery(); doReturn(CustomResultSetExtractor.class).when(queryMethod).getResultSetExtractorClass(); - new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter).execute(new Object[] {}); + new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter, beanFactory).execute(new Object[] {}); - StringBasedJdbcQuery query = new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter); + StringBasedJdbcQuery query = new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter, beanFactory); ResultSetExtractor resultSetExtractor = query.determineResultSetExtractor(defaultRowMapper); @@ -134,7 +137,7 @@ public class StringBasedJdbcQueryUnitTests { doReturn(CustomResultSetExtractor.class).when(queryMethod).getResultSetExtractorClass(); doReturn(CustomRowMapper.class).when(queryMethod).getRowMapperClass(); - StringBasedJdbcQuery query = new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter); + StringBasedJdbcQuery query = new StringBasedJdbcQuery(queryMethod, operations, defaultRowMapper, converter, beanFactory); ResultSetExtractor resultSetExtractor = query .determineResultSetExtractor(query.determineRowMapper(defaultRowMapper)); diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategyUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategyUnitTests.java index cb213c9e..d4bad9b5 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategyUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategyUnitTests.java @@ -24,6 +24,7 @@ import java.text.NumberFormat; import org.junit.Before; import org.junit.Test; +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; @@ -61,6 +62,7 @@ public class JdbcQueryLookupStrategyUnitTests { ProjectionFactory projectionFactory = mock(ProjectionFactory.class); RepositoryMetadata metadata; NamedQueries namedQueries = mock(NamedQueries.class); + BeanFactory beanFactory = mock(BeanFactory.class); NamedParameterJdbcOperations operations = mock(NamedParameterJdbcOperations.class); @Before @@ -90,7 +92,7 @@ public class JdbcQueryLookupStrategyUnitTests { private RepositoryQuery getRepositoryQuery(String name, QueryMappingConfiguration mappingConfiguration) { JdbcQueryLookupStrategy queryLookupStrategy = new JdbcQueryLookupStrategy(publisher, callbacks, mappingContext, - converter, H2Dialect.INSTANCE, mappingConfiguration, operations); + converter, H2Dialect.INSTANCE, mappingConfiguration, operations, beanFactory); Method method = ReflectionUtils.findMethod(MyRepository.class, name); return queryLookupStrategy.resolveQuery(method, metadata, projectionFactory, namedQueries); diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/SingleBaseMappingTestConfiguration.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/SingleBaseMappingTestConfiguration.java new file mode 100644 index 00000000..584e3556 --- /dev/null +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/SingleBaseMappingTestConfiguration.java @@ -0,0 +1,75 @@ +package org.springframework.data.jdbc.testing; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.dao.DataAccessException; +import org.springframework.data.annotation.Id; +import org.springframework.jdbc.core.ResultSetExtractor; +import org.springframework.jdbc.core.RowMapper; + +@Configuration +public class SingleBaseMappingTestConfiguration { + + public final static String VALUE_PROCESSED_BY_SERVICE = "Value Processed by Service"; + + @Bean(value = "CarResultSetExtractorBean") + public CarResultSetExtractorBean resultSetExtractorBean() { + return new CarResultSetExtractorBean(); + } + + @Bean + public CustomerService service() { + return new CustomerService(); + } + + @Bean(value = "CustomRowMapperBean") + public CustomRowMapperBean rowMapperBean() { + return new CustomRowMapperBean(); + } + + public static class CarResultSetExtractorBean implements ResultSetExtractor> { + + @Autowired + private CustomerService customerService; + + @Override + public List extractData(ResultSet rs) throws SQLException, DataAccessException { + return Arrays.asList(new Car(1L, customerService.process())); + } + + } + + public static class CustomRowMapperBean implements RowMapper { + + @Autowired + private CustomerService customerService; + + public String mapRow(ResultSet rs, int rowNum) throws SQLException { + return customerService.process(); + } + } + + public static class CustomerService { + public String process() { + return VALUE_PROCESSED_BY_SERVICE; + } + } + + @Data + @AllArgsConstructor + public static class Car { + + @Id + private Long id; + private String model; + } +} diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java index 7e8b1ccd..7d0aafb7 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java @@ -15,18 +15,24 @@ */ package org.springframework.data.jdbc.testing; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; import java.util.Optional; import javax.sql.DataSource; +import lombok.AllArgsConstructor; +import lombok.Data; import org.apache.ibatis.session.SqlSessionFactory; +import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.*; +import org.springframework.dao.DataAccessException; +import org.springframework.data.annotation.Id; import org.springframework.data.convert.CustomConversions; import org.springframework.data.jdbc.core.convert.BasicJdbcConverter; import org.springframework.data.jdbc.core.convert.DataAccessStrategy; @@ -43,6 +49,8 @@ import org.springframework.data.relational.core.dialect.Dialect; import org.springframework.data.relational.core.mapping.NamingStrategy; import org.springframework.data.relational.core.mapping.RelationalMappingContext; import org.springframework.data.repository.core.NamedQueries; +import org.springframework.jdbc.core.ResultSetExtractor; +import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; @@ -62,6 +70,7 @@ import org.springframework.transaction.PlatformTransactionManager; public class TestConfiguration { @Autowired DataSource dataSource; + @Autowired BeanFactory beanFactory; @Autowired ApplicationEventPublisher publisher; @Autowired(required = false) SqlSessionFactory sqlSessionFactory; @@ -71,7 +80,7 @@ public class TestConfiguration { Dialect dialect, JdbcConverter converter, Optional namedQueries) { JdbcRepositoryFactory factory = new JdbcRepositoryFactory(dataAccessStrategy, context, converter, dialect, - publisher, namedParameterJdbcTemplate()); + publisher, namedParameterJdbcTemplate(), beanFactory); namedQueries.ifPresent(factory::setNamedQueries); return factory; }