15
15
*/
16
16
package org .springframework .data .jdbc .core .convert ;
17
17
18
- import java .util .*;
18
+ import java .util .ArrayList ;
19
+ import java .util .Collection ;
20
+ import java .util .Collections ;
21
+ import java .util .Comparator ;
22
+ import java .util .HashSet ;
23
+ import java .util .LinkedHashSet ;
24
+ import java .util .List ;
25
+ import java .util .Map ;
26
+ import java .util .Set ;
27
+ import java .util .TreeSet ;
19
28
import java .util .function .BiFunction ;
20
29
import java .util .function .Function ;
21
30
import java .util .function .Predicate ;
38
47
import org .springframework .data .relational .core .sql .*;
39
48
import org .springframework .data .relational .core .sql .render .SqlRenderer ;
40
49
import org .springframework .data .util .Lazy ;
41
- import org .springframework .data .util .Pair ;
42
50
import org .springframework .data .util .Predicates ;
43
51
import org .springframework .jdbc .core .namedparam .MapSqlParameterSource ;
44
52
import org .springframework .lang .Nullable ;
@@ -123,11 +131,11 @@ public class SqlGenerator {
123
131
* @param table the table to base the select on
124
132
* @param pathFilter a filter for excluding paths from the select. All paths for which the filter returns
125
133
* {@literal true} will be skipped when determining columns to select.
126
- * @return A select structure suitable for constructing more specialized selects by adding conditions.
134
+ * @return a select structure suitable for constructing more specialized selects by adding conditions.
127
135
* @since 4.0
128
136
*/
129
137
public SelectBuilder .SelectWhere createSelectBuilder (Table table , Predicate <AggregatePath > pathFilter ) {
130
- return createSelectBuilder (table , pathFilter , Collections .emptyList ());
138
+ return createSelectBuilder (table , pathFilter , Collections .emptyList (), Query . empty () );
131
139
}
132
140
133
141
/**
@@ -188,13 +196,7 @@ private Condition getSubselectCondition(AggregatePath path,
188
196
AggregatePath .TableInfo parentPathTableInfo = parentPath .getTableInfo ();
189
197
Table subSelectTable = Table .create (parentPathTableInfo .qualifiedTableName ());
190
198
191
- Map <AggregatePath , Column > selectFilterColumns = new TreeMap <>();
192
-
193
- // TODO: cannot we simply pass on the columnInfos?
194
- parentPathTableInfo .effectiveIdColumnInfos ().forEach ( //
195
- (ap , ci ) -> //
196
- selectFilterColumns .put (ap , subSelectTable .column (ci .name ())) //
197
- );
199
+ Map <AggregatePath , Column > selectFilterColumns = parentPathTableInfo .effectiveIdColumnInfos ().toMap (subSelectTable );
198
200
199
201
Condition innerCondition ;
200
202
@@ -609,29 +611,24 @@ private SelectBuilder.SelectWhere selectBuilder(Collection<SqlIdentifier> keyCol
609
611
}
610
612
611
613
private SelectBuilder .SelectWhere selectBuilder (Collection <SqlIdentifier > keyColumns , Query query ) {
612
-
613
- return createSelectBuilder (getTable (), ap -> false , keyColumns );
614
+ return createSelectBuilder (getTable (), ap -> false , keyColumns , query );
614
615
}
615
616
616
617
private SelectBuilder .SelectWhere createSelectBuilder (Table table , Predicate <AggregatePath > pathFilter ,
617
- Collection <SqlIdentifier > keyColumns ) {
618
+ Collection <SqlIdentifier > keyColumns , Query query ) {
618
619
619
620
Projection projection = getProjection (pathFilter , keyColumns , query , table );
620
621
SelectBuilder .SelectJoin baseSelect = StatementBuilder .select (projection .columns ()).from (table );
621
622
622
- return (SelectBuilder .SelectWhere ) addJoins (baseSelect , joinTables );
623
+ return (SelectBuilder .SelectWhere ) addJoins (baseSelect , projection . joins () );
623
624
}
624
625
625
- private static SelectBuilder .SelectJoin addJoins (SelectBuilder .SelectJoin baseSelect , List <Join > joinTables ) {
626
-
627
- for (Join join : projection .joins ()) {
628
-
629
- baseSelect = baseSelect .leftOuterJoin (join .joinTable ).on (join .condition );
630
- }
631
- return baseSelect ;
626
+ private static SelectBuilder .SelectJoin addJoins (SelectBuilder .SelectJoin baseSelect , Joins joins ) {
627
+ return joins .reduce (baseSelect , (join , select ) -> select .leftOuterJoin (join .joinTable ).on (join .condition ));
632
628
}
633
629
634
- private Projection getProjection (Predicate <AggregatePath > pathFilter , Collection <SqlIdentifier > keyColumns , Query query , Table table ) {
630
+ private Projection getProjection (Predicate <AggregatePath > pathFilter , Collection <SqlIdentifier > keyColumns ,
631
+ Query query , Table table ) {
635
632
636
633
Set <Expression > columns = new LinkedHashSet <>();
637
634
Set <Join > joins = new LinkedHashSet <>();
@@ -642,7 +639,7 @@ private Projection getProjection(Predicate<AggregatePath> pathFilter, Collection
642
639
AggregatePath aggregatePath = mappingContext .getAggregatePath (
643
640
mappingContext .getPersistentPropertyPath (columnName .getReference (), entity .getTypeInformation ()));
644
641
645
- includeColumnAndJoin (aggregatePath , joins , columns );
642
+ includeColumnAndJoin (aggregatePath , pathFilter , joins , columns );
646
643
} catch (InvalidPersistentPropertyPath e ) {
647
644
columns .add (Column .create (columnName , table ));
648
645
}
@@ -656,22 +653,40 @@ private Projection getProjection(Predicate<AggregatePath> pathFilter, Collection
656
653
AggregatePath aggregatePath = mappingContext .getAggregatePath (path );
657
654
658
655
if (pathFilter .test (aggregatePath )) {
659
- continue ;
660
- }
656
+ continue ;
657
+ }
661
658
662
- includeColumnAndJoin (aggregatePath , joins , columns );
659
+ includeColumnAndJoin (aggregatePath , pathFilter , joins , columns );
663
660
}
664
661
}
665
662
666
663
for (SqlIdentifier keyColumn : keyColumns ) {
667
664
columns .add (table .column (keyColumn ).as (keyColumn ));
668
665
}
669
666
670
- return new Projection (columns , joins );
667
+ return new Projection (columns , Joins . of ( joins ) );
671
668
}
672
669
673
- private void includeColumnAndJoin (AggregatePath aggregatePath , Collection <Join > joins ,
674
- Collection <Expression > columns ) {
670
+ private void includeColumnAndJoin (AggregatePath aggregatePath , Predicate <AggregatePath > pathFilter ,
671
+ Collection <Join > joins , Collection <Expression > columns ) {
672
+
673
+ if (aggregatePath .isEmbedded ()) {
674
+
675
+ RelationalPersistentEntity <?> entity = aggregatePath .getRequiredLeafEntity ();
676
+
677
+ for (RelationalPersistentProperty property : entity ) {
678
+
679
+ AggregatePath nested = aggregatePath .append (property );
680
+
681
+ if (pathFilter .test (nested )) {
682
+ continue ;
683
+ }
684
+
685
+ includeColumnAndJoin (nested , pathFilter , joins , columns );
686
+ }
687
+
688
+ return ;
689
+ }
675
690
676
691
joins .addAll (getJoins (aggregatePath ));
677
692
@@ -687,7 +702,24 @@ private void includeColumnAndJoin(AggregatePath aggregatePath, Collection<Join>
687
702
* @param columns
688
703
* @param joins
689
704
*/
690
- record Projection (Set <Expression > columns , Set <Join > joins ) {
705
+ record Projection (Collection <Expression > columns , Joins joins ) {
706
+
707
+ }
708
+
709
+ record Joins (Collection <Join > joins ) {
710
+
711
+ public static Joins of (Collection <Join > joins ) {
712
+ return new Joins (joins );
713
+ }
714
+
715
+ public <T > T reduce (T identity , BiFunction <Join , T , T > accumulator ) {
716
+
717
+ T result = identity ;
718
+ for (Join join : joins ) {
719
+ result = accumulator .apply (join , result );
720
+ }
721
+ return result ;
722
+ }
691
723
}
692
724
693
725
private SelectBuilder .SelectOrdered selectBuilder (Collection <SqlIdentifier > keyColumns , Sort sort ,
@@ -922,11 +954,8 @@ private String createDeleteByPathAndCriteria(AggregatePath path,
922
954
.from (table );
923
955
Delete delete ;
924
956
925
- Map <AggregatePath , Column > columns = new TreeMap <>();
926
957
AggregatePath .ColumnInfos columnInfos = path .getTableInfo ().backReferenceColumnInfos ();
927
-
928
- // TODO: cannot we simply pass on the columnInfos?
929
- columnInfos .forEach ((ag , ci ) -> columns .put (ag , table .column (ci .name ())));
958
+ Map <AggregatePath , Column > columns = columnInfos .toMap (table );
930
959
931
960
if (isFirstNonRoot (path )) {
932
961
@@ -978,22 +1007,19 @@ private Table getTable() {
978
1007
* @return a single column of the primary key to be used in places where one need something not null to be selected.
979
1008
*/
980
1009
private Column getSingleNonNullColumn () {
981
-
982
- // getColumn() is slightly different from the code in any(…). Why?
983
- // AggregatePath.ColumnInfo columnInfo = path.getColumnInfo();
984
- // return getTable(path).column(columnInfo.name()).as(columnInfo.alias());
985
-
986
- AggregatePath .ColumnInfos columnInfos = mappingContext .getAggregatePath (entity ).getTableInfo ().idColumnInfos ();
987
- return columnInfos .any ((ap , ci ) -> sqlContext .getColumn (ap ));
1010
+ return doGetColumn (AggregatePath .ColumnInfos ::any );
988
1011
}
989
1012
990
1013
private List <Column > getIdColumns () {
1014
+ return doGetColumn (AggregatePath .ColumnInfos ::toColumnList );
1015
+ }
1016
+
1017
+ private <T > T doGetColumn (
1018
+ BiFunction <AggregatePath .ColumnInfos , BiFunction <AggregatePath , AggregatePath .ColumnInfo , Column >, T > columnListFunction ) {
991
1019
992
1020
AggregatePath .ColumnInfos columnInfos = mappingContext .getAggregatePath (entity ).getTableInfo ().idColumnInfos ();
993
1021
994
- // sqlcontext.getColumn (vs sqlContext.getTable
995
- return columnInfos
996
- .toColumnList ((aggregatePath , columnInfo ) -> sqlContext .getColumn (aggregatePath ));
1022
+ return columnListFunction .apply (columnInfos , (aggregatePath , columnInfo ) -> sqlContext .getColumn (aggregatePath ));
997
1023
}
998
1024
999
1025
private Column getVersionColumn () {
@@ -1164,7 +1190,7 @@ private SelectBuilder.SelectJoin getExistsSelect() {
1164
1190
}
1165
1191
}
1166
1192
1167
- return addJoins (baseSelect , joins );
1193
+ return addJoins (baseSelect , Joins . of ( joins ) );
1168
1194
}
1169
1195
1170
1196
/**
@@ -1199,7 +1225,7 @@ private SelectBuilder.SelectJoin getSelectCountWithExpression(Expression... coun
1199
1225
joins .add (join );
1200
1226
}
1201
1227
}
1202
- return addJoins (baseSelect , joins );
1228
+ return addJoins (baseSelect , Joins . of ( joins ) );
1203
1229
}
1204
1230
1205
1231
private SelectBuilder .SelectOrdered applyQueryOnSelect (Query query , MapSqlParameterSource parameterSource ,
0 commit comments