Skip to content

Commit 155004e

Browse files
committed
JdbcAggregateTemplate honors columns specified in query.
If no columns are given, all columns are selected by default. If columns are specified, only these are selected. Joins normally triggered by columns from 1:1 relationships are not implemented, and the corresponding columns don't get loaded and can't be specified in a query. Limiting columns is not supported for single query loading. Closes #1803
1 parent 7050464 commit 155004e

File tree

3 files changed

+71
-15
lines changed

3 files changed

+71
-15
lines changed

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

+31-13
Original file line numberDiff line numberDiff line change
@@ -507,33 +507,50 @@ private String createFindAllSql() {
507507
}
508508

509509
private SelectBuilder.SelectWhere selectBuilder() {
510-
return selectBuilder(Collections.emptyList());
510+
return selectBuilder(Collections.emptyList(), null);
511+
}
512+
513+
514+
private SelectBuilder.SelectWhere selectBuilder(Query query) {
515+
return selectBuilder(Collections.emptyList(), query);
511516
}
512517

513518
private SelectBuilder.SelectWhere selectBuilder(Collection<SqlIdentifier> keyColumns) {
519+
return selectBuilder(keyColumns, null);
520+
}
521+
522+
private SelectBuilder.SelectWhere selectBuilder(Collection<SqlIdentifier> keyColumns, @Nullable Query query) {
514523

515524
Table table = getTable();
516525

517526
Set<Expression> columnExpressions = new LinkedHashSet<>();
518527

519528
List<Join> joinTables = new ArrayList<>();
520-
for (PersistentPropertyPath<RelationalPersistentProperty> path : mappingContext
521-
.findPersistentPropertyPaths(entity.getType(), p -> true)) {
522529

523-
AggregatePath extPath = mappingContext.getAggregatePath(path);
524-
525-
// add a join if necessary
526-
Join join = getJoin(extPath);
527-
if (join != null) {
528-
joinTables.add(join);
530+
if (query != null && !query.getColumns().isEmpty()) {
531+
for (SqlIdentifier columnName : query.getColumns()) {
532+
columnExpressions.add(Column.create(columnName, table));
529533
}
534+
} else {
535+
for (PersistentPropertyPath<RelationalPersistentProperty> path : mappingContext
536+
.findPersistentPropertyPaths(entity.getType(), p -> true)) {
537+
538+
AggregatePath extPath = mappingContext.getAggregatePath(path);
539+
540+
// add a join if necessary
541+
Join join = getJoin(extPath);
542+
if (join != null) {
543+
joinTables.add(join);
544+
}
530545

531-
Column column = getColumn(extPath);
532-
if (column != null) {
533-
columnExpressions.add(column);
546+
Column column = getColumn(extPath);
547+
if (column != null) {
548+
columnExpressions.add(column);
549+
}
534550
}
535551
}
536552

553+
537554
for (SqlIdentifier keyColumn : keyColumns) {
538555
columnExpressions.add(table.column(keyColumn).as(keyColumn));
539556
}
@@ -876,14 +893,15 @@ public String selectByQuery(Query query, MapSqlParameterSource parameterSource)
876893

877894
Assert.notNull(parameterSource, "parameterSource must not be null");
878895

879-
SelectBuilder.SelectWhere selectBuilder = selectBuilder();
896+
SelectBuilder.SelectWhere selectBuilder = selectBuilder(query);
880897

881898
Select select = applyQueryOnSelect(query, parameterSource, selectBuilder) //
882899
.build();
883900

884901
return render(select);
885902
}
886903

904+
887905
/**
888906
* Constructs a single sql query that performs select based on the provided query and pagination information.
889907
* Additional the bindings for the where clause are stored after execution into the <code>parameterSource</code>

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

+25-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.stream.IntStream;
3030

3131
import org.assertj.core.api.SoftAssertions;
32+
import org.junit.jupiter.api.Disabled;
3233
import org.junit.jupiter.api.Test;
3334
import org.springframework.beans.factory.annotation.Autowired;
3435
import org.springframework.context.ApplicationEventPublisher;
@@ -235,7 +236,25 @@ void findAllByQuery() {
235236
Query query = Query.query(criteria);
236237
Iterable<SimpleListParent> reloadedById = template.findAll(query, SimpleListParent.class);
237238

238-
assertThat(reloadedById).extracting(e -> e.id, e -> e.content.size()).containsExactly(tuple(two.id, 2));
239+
assertThat(reloadedById) //
240+
.extracting(e -> e.id, e-> e.name, e -> e.content.size()) //
241+
.containsExactly(tuple(two.id, two.name, 2));
242+
}
243+
244+
@Test // GH-1803
245+
void findAllByQueryWithColumns() {
246+
247+
template.save(SimpleListParent.of("one", "one_1"));
248+
SimpleListParent two = template.save(SimpleListParent.of("two", "two_1", "two_2"));
249+
template.save(SimpleListParent.of("three", "three_1", "three_2", "three_3"));
250+
251+
CriteriaDefinition criteria = CriteriaDefinition.from(Criteria.where("id").is(two.id));
252+
Query query = Query.query(criteria).columns("id");
253+
Iterable<SimpleListParent> reloadedById = template.findAll(query, SimpleListParent.class);
254+
255+
assertThat(reloadedById) //
256+
.extracting(e -> e.id, e-> e.name, e -> e.content.size()) //
257+
.containsExactly(tuple(two.id, null, 2));
239258
}
240259

241260
@Test // GH-1601
@@ -2240,5 +2259,10 @@ static class JdbcAggregateTemplateIntegrationTests extends AbstractJdbcAggregate
22402259
static class JdbcAggregateTemplateSingleQueryLoadingIntegrationTests
22412260
extends AbstractJdbcAggregateTemplateIntegrationTests {
22422261

2262+
@Disabled
2263+
@Override
2264+
void findAllByQueryWithColumns() {
2265+
super.findAllByQueryWithColumns();
2266+
}
22432267
}
22442268
}

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

+15-1
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,19 @@ void selectByQuery() {
358358
);
359359
}
360360

361+
@Test // GH-1803
362+
void selectByQueryWithColumnLimit() {
363+
364+
Query query = Query.empty().columns("alpha", "beta", "gamma");
365+
366+
String sql = sqlGenerator.selectByQuery(query, new MapSqlParameterSource());
367+
368+
assertThat(sql).contains( //
369+
"SELECT dummy_entity.alpha, dummy_entity.beta, dummy_entity.gamma", //
370+
"FROM dummy_entity" //
371+
);
372+
}
373+
361374
@Test // GH-1919
362375
void selectBySortedQuery() {
363376

@@ -375,7 +388,8 @@ void selectBySortedQuery() {
375388
"ORDER BY dummy_entity.id1 ASC" //
376389
);
377390
assertThat(sql).containsOnlyOnce("LEFT OUTER JOIN referenced_entity ref ON ref.dummy_entity = dummy_entity.id1");
378-
assertThat(sql).containsOnlyOnce("LEFT OUTER JOIN second_level_referenced_entity ref_further ON ref_further.referenced_entity = ref.x_l1id");
391+
assertThat(sql).containsOnlyOnce(
392+
"LEFT OUTER JOIN second_level_referenced_entity ref_further ON ref_further.referenced_entity = ref.x_l1id");
379393
}
380394

381395
@Test // DATAJDBC-131, DATAJDBC-111

0 commit comments

Comments
 (0)