Skip to content

Commit a8a3f87

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 4017576 commit a8a3f87

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

Lines changed: 31 additions & 13 deletions
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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.stream.IntStream;
3030
import java.util.stream.Stream;
3131

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
@@ -2283,5 +2302,10 @@ static class JdbcAggregateTemplateIntegrationTests extends AbstractJdbcAggregate
22832302
static class JdbcAggregateTemplateSingleQueryLoadingIntegrationTests
22842303
extends AbstractJdbcAggregateTemplateIntegrationTests {
22852304

2305+
@Disabled
2306+
@Override
2307+
void findAllByQueryWithColumns() {
2308+
super.findAllByQueryWithColumns();
2309+
}
22862310
}
22872311
}

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,19 @@ void selectByQuery() {
364364
);
365365
}
366366

367+
@Test // GH-1803
368+
void selectByQueryWithColumnLimit() {
369+
370+
Query query = Query.empty().columns("alpha", "beta", "gamma");
371+
372+
String sql = sqlGenerator.selectByQuery(query, new MapSqlParameterSource());
373+
374+
assertThat(sql).contains( //
375+
"SELECT dummy_entity.alpha, dummy_entity.beta, dummy_entity.gamma", //
376+
"FROM dummy_entity" //
377+
);
378+
}
379+
367380
@Test // GH-1919
368381
void selectBySortedQuery() {
369382

@@ -381,7 +394,8 @@ void selectBySortedQuery() {
381394
"ORDER BY dummy_entity.id1 ASC" //
382395
);
383396
assertThat(sql).containsOnlyOnce("LEFT OUTER JOIN referenced_entity ref ON ref.dummy_entity = dummy_entity.id1");
384-
assertThat(sql).containsOnlyOnce("LEFT OUTER JOIN second_level_referenced_entity ref_further ON ref_further.referenced_entity = ref.x_l1id");
397+
assertThat(sql).containsOnlyOnce(
398+
"LEFT OUTER JOIN second_level_referenced_entity ref_further ON ref_further.referenced_entity = ref.x_l1id");
385399
}
386400

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

0 commit comments

Comments
 (0)