Avoid superfluous creation of RowMappers.

For modifying queries RowMappers get now longer created.
Improved documentation for `@Query` annotation.

Original pull request #1423
This commit is contained in:
Mikhail2048
2023-02-05 16:52:47 +03:00
committed by Jens Schauder
parent 761f0087c8
commit 468f94b312
4 changed files with 47 additions and 24 deletions

View File

@@ -82,10 +82,6 @@ public abstract class AbstractJdbcQuery implements RepositoryQuery {
protected JdbcQueryExecution<?> getQueryExecution(JdbcQueryMethod queryMethod,
@Nullable ResultSetExtractor<?> extractor, RowMapper<?> rowMapper) {
if (queryMethod.isModifyingQuery()) {
return createModifyingQueryExecutor();
}
if (queryMethod.isCollectionQuery()) {
return extractor != null ? getQueryExecution(extractor) : collectionQuery(rowMapper);
}
@@ -97,7 +93,7 @@ public abstract class AbstractJdbcQuery implements RepositoryQuery {
return extractor != null ? getQueryExecution(extractor) : singleObjectQuery(rowMapper);
}
private JdbcQueryExecution<Object> createModifyingQueryExecutor() {
protected JdbcQueryExecution<Object> createModifyingQueryExecutor() {
return (query, parameters) -> {

View File

@@ -43,6 +43,7 @@ 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.SqlParameterSource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -144,9 +145,7 @@ public class PartTreeJdbcQuery extends AbstractJdbcQuery {
resultProcessingConverter);
}
JdbcQueryExecution<?> queryExecution = getQueryMethod().isPageQuery() || getQueryMethod().isSliceQuery()
? collectionQuery(rowMapper)
: getQueryExecution(getQueryMethod(), extractor, rowMapper);
JdbcQueryExecution<?> queryExecution = getJdbcQueryExecution(extractor, rowMapper);
if (getQueryMethod().isSliceQuery()) {
return new SliceQueryExecution<>((JdbcQueryExecution<Collection<Object>>) queryExecution, accessor.getPageable());
@@ -173,6 +172,18 @@ public class PartTreeJdbcQuery extends AbstractJdbcQuery {
return queryExecution;
}
private JdbcQueryExecution<?> getJdbcQueryExecution(@Nullable ResultSetExtractor<Boolean> extractor, RowMapper<Object> rowMapper) {
if (getQueryMethod().isPageQuery() || getQueryMethod().isSliceQuery()) {
return collectionQuery(rowMapper);
} else {
if (getQueryMethod().isModifyingQuery()) {
return createModifyingQueryExecutor();
} else {
return getQueryExecution(getQueryMethod(), extractor, rowMapper);
}
}
}
protected ParametrizedQuery createQuery(RelationalParametersParameterAccessor accessor, ReturnedType returnedType) {
RelationalEntityMetadata<?> entityMetadata = getQueryMethod().getEntityInformation();

View File

@@ -29,6 +29,18 @@ import org.springframework.jdbc.core.RowMapper;
* Annotation to provide SQL statements that will get used for executing the method. The SQL statement may contain named
* parameters as supported by {@link org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate}. Those
* parameters will get bound to the arguments of the annotated method.
* <p>
* You can also specify the way to extract data from {@link java.sql.ResultSet}. There are 4 attribute of this
* annotation you can set to do that:
* <p>
* 1. {@link #resultSetExtractorRef()}
* 2. {@link #resultSetExtractorClass()}
* 3. {@link #rowMapperRef()}
* 4. {@link #rowMapperClass()}
*
* The annotation attributes above are listed in their preference order, that is - the {@link #resultSetExtractorRef()},
* has the highest privilege and, will suppress any other 3 attribute from above, and consequently {@link #rowMapperClass()}
* has the lowest privilege and will be used if any of three above are not specified.
*
* @author Jens Schauder
* @author Moises Cisneros
@@ -52,28 +64,23 @@ public @interface Query {
String name() default "";
/**
* 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.
*/
Class<? extends RowMapper> rowMapperClass() default RowMapper.class;
/**
* Optional name of a 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.
*
* Optional name of a bean of type {@link RowMapper} to use to convert the result of the query to domain class instances.
* @since 2.1
*/
String rowMapperRef() default "";
/**
* 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.
*/
Class<? extends ResultSetExtractor> resultSetExtractorClass() default ResultSetExtractor.class;
/**
* Optional name of a 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.
* Optional name of a bean of type {@link ResultSetExtractor} to use to convert the result of the query to domain class instances.
*
* @since 2.1
*/

View File

@@ -128,13 +128,7 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery {
ResultProcessingConverter converter = new ResultProcessingConverter(processor, this.converter.getMappingContext(),
this.converter.getEntityInstantiators());
RowMapper<Object> rowMapper = determineRowMapper(rowMapperFactory.create(resolveTypeToRead(processor)), converter,
accessor.findDynamicProjection() != null);
JdbcQueryExecution<?> queryExecution = getQueryExecution(//
queryMethod, //
determineResultSetExtractor(rowMapper), //
rowMapper);
JdbcQueryExecution<?> queryExecution = createJdbcQueryExecution(accessor, processor, converter);
MapSqlParameterSource parameterMap = this.bindParameters(accessor);
@@ -147,6 +141,21 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery {
return queryExecution.execute(processSpelExpressions(objects, parameterMap, query), parameterMap);
}
private JdbcQueryExecution<?> createJdbcQueryExecution(RelationalParameterAccessor accessor, ResultProcessor processor, ResultProcessingConverter converter) {
JdbcQueryExecution<?> queryExecution;
if (queryMethod.isModifyingQuery()) {
queryExecution = createModifyingQueryExecutor();
} else {
RowMapper<Object> rowMapper = determineRowMapper(rowMapperFactory.create(resolveTypeToRead(processor)), converter,
accessor.findDynamicProjection() != null);
queryExecution = getQueryExecution(queryMethod, determineResultSetExtractor(rowMapper), rowMapper);
}
return queryExecution;
}
private String processSpelExpressions(Object[] objects, MapSqlParameterSource parameterMap, String query) {
SpelQueryContext.EvaluatingSpelQueryContext queryContext = SpelQueryContext