16
16
package org .springframework .data .jdbc .repository .query ;
17
17
18
18
import java .sql .ResultSet ;
19
-
19
+ import java .util .ArrayList ;
20
+ import java .util .Collection ;
21
+ import java .util .List ;
22
+ import java .util .function .LongSupplier ;
23
+
24
+ import org .springframework .data .domain .Pageable ;
25
+ import org .springframework .data .domain .Slice ;
26
+ import org .springframework .data .domain .SliceImpl ;
20
27
import org .springframework .data .domain .Sort ;
21
28
import org .springframework .data .jdbc .core .convert .JdbcConverter ;
22
29
import org .springframework .data .relational .core .dialect .Dialect ;
26
33
import org .springframework .data .relational .repository .query .RelationalParametersParameterAccessor ;
27
34
import org .springframework .data .repository .query .Parameters ;
28
35
import org .springframework .data .repository .query .parser .PartTree ;
36
+ import org .springframework .data .support .PageableExecutionUtils ;
29
37
import org .springframework .jdbc .core .ResultSetExtractor ;
30
38
import org .springframework .jdbc .core .RowMapper ;
31
39
import org .springframework .jdbc .core .namedparam .NamedParameterJdbcOperations ;
40
+ import org .springframework .jdbc .core .namedparam .SqlParameterSource ;
32
41
import org .springframework .util .Assert ;
33
42
34
43
/**
@@ -46,6 +55,7 @@ public class PartTreeJdbcQuery extends AbstractJdbcQuery {
46
55
private final JdbcConverter converter ;
47
56
private final PartTree tree ;
48
57
private final JdbcQueryExecution <?> execution ;
58
+ private final RowMapper <Object > rowMapper ;
49
59
50
60
/**
51
61
* Creates a new {@link PartTreeJdbcQuery}.
@@ -77,7 +87,9 @@ public PartTreeJdbcQuery(RelationalMappingContext context, JdbcQueryMethod query
77
87
78
88
ResultSetExtractor <Boolean > extractor = tree .isExistsProjection () ? (ResultSet ::next ) : null ;
79
89
80
- this .execution = getQueryExecution (queryMethod , extractor , rowMapper );
90
+ this .execution = queryMethod .isPageQuery () || queryMethod .isSliceQuery () ? collectionQuery (rowMapper )
91
+ : getQueryExecution (queryMethod , extractor , rowMapper );
92
+ this .rowMapper = rowMapper ;
81
93
}
82
94
83
95
private Sort getDynamicSort (RelationalParameterAccessor accessor ) {
@@ -93,15 +105,108 @@ public Object execute(Object[] values) {
93
105
94
106
RelationalParametersParameterAccessor accessor = new RelationalParametersParameterAccessor (getQueryMethod (),
95
107
values );
96
-
97
108
ParametrizedQuery query = createQuery (accessor );
98
- return this .execution .execute (query .getQuery (), query .getParameterSource ());
109
+ JdbcQueryExecution <?> execution = getQueryExecution (accessor );
110
+
111
+ return execution .execute (query .getQuery (), query .getParameterSource ());
112
+ }
113
+
114
+ private JdbcQueryExecution <?> getQueryExecution (RelationalParametersParameterAccessor accessor ) {
115
+
116
+ if (getQueryMethod ().isSliceQuery ()) {
117
+ return new SliceQueryExecution <>((JdbcQueryExecution <Collection <Object >>) this .execution , accessor .getPageable ());
118
+ }
119
+
120
+ if (getQueryMethod ().isPageQuery ()) {
121
+
122
+ return new PageQueryExecution <>((JdbcQueryExecution <Collection <Object >>) this .execution , accessor .getPageable (),
123
+ () -> {
124
+
125
+ RelationalEntityMetadata <?> entityMetadata = getQueryMethod ().getEntityInformation ();
126
+
127
+ JdbcCountQueryCreator queryCreator = new JdbcCountQueryCreator (context , tree , converter , dialect ,
128
+ entityMetadata , accessor , false );
129
+
130
+ ParametrizedQuery countQuery = queryCreator .createQuery (Sort .unsorted ());
131
+ Object count = singleObjectQuery ((rs , i ) -> rs .getLong (1 )).execute (countQuery .getQuery (),
132
+ countQuery .getParameterSource ());
133
+
134
+ return converter .getConversionService ().convert (count , Long .class );
135
+ });
136
+ }
137
+
138
+ return this .execution ;
99
139
}
100
140
101
141
protected ParametrizedQuery createQuery (RelationalParametersParameterAccessor accessor ) {
102
142
103
143
RelationalEntityMetadata <?> entityMetadata = getQueryMethod ().getEntityInformation ();
104
- JdbcQueryCreator queryCreator = new JdbcQueryCreator (context , tree , converter , dialect , entityMetadata , accessor );
144
+
145
+ JdbcQueryCreator queryCreator = new JdbcQueryCreator (context , tree , converter , dialect , entityMetadata , accessor ,
146
+ getQueryMethod ().isSliceQuery ());
105
147
return queryCreator .createQuery (getDynamicSort (accessor ));
106
148
}
149
+
150
+ /**
151
+ * {@link JdbcQueryExecution} returning a {@link org.springframework.data.domain.Slice}.
152
+ *
153
+ * @param <T>
154
+ */
155
+ static class SliceQueryExecution <T > implements JdbcQueryExecution <Slice <T >> {
156
+
157
+ private final JdbcQueryExecution <? extends Collection <T >> delegate ;
158
+ private final Pageable pageable ;
159
+
160
+ public SliceQueryExecution (JdbcQueryExecution <? extends Collection <T >> delegate , Pageable pageable ) {
161
+ this .delegate = delegate ;
162
+ this .pageable = pageable ;
163
+ }
164
+
165
+ @ Override
166
+ public Slice <T > execute (String query , SqlParameterSource parameter ) {
167
+
168
+ Collection <T > result = delegate .execute (query , parameter );
169
+
170
+ int pageSize = 0 ;
171
+ if (pageable .isPaged ()) {
172
+
173
+ pageSize = pageable .getPageSize ();
174
+ }
175
+
176
+ List <T > resultList = result instanceof List ? (List <T >) result : new ArrayList <>(result );
177
+
178
+ boolean hasNext = pageable .isPaged () && resultList .size () > pageSize ;
179
+
180
+ return new SliceImpl <>(hasNext ? resultList .subList (0 , pageSize ) : resultList , pageable , hasNext );
181
+ }
182
+ }
183
+
184
+ /**
185
+ * {@link JdbcQueryExecution} returning a {@link org.springframework.data.domain.Page}.
186
+ *
187
+ * @param <T>
188
+ */
189
+ static class PageQueryExecution <T > implements JdbcQueryExecution <Slice <T >> {
190
+
191
+ private final JdbcQueryExecution <? extends Collection <T >> delegate ;
192
+ private final Pageable pageable ;
193
+ private final LongSupplier countSupplier ;
194
+
195
+ public PageQueryExecution (JdbcQueryExecution <? extends Collection <T >> delegate , Pageable pageable ,
196
+ LongSupplier countSupplier ) {
197
+ this .delegate = delegate ;
198
+ this .pageable = pageable ;
199
+ this .countSupplier = countSupplier ;
200
+ }
201
+
202
+ @ Override
203
+ public Slice <T > execute (String query , SqlParameterSource parameter ) {
204
+
205
+ Collection <T > result = delegate .execute (query , parameter );
206
+
207
+ return PageableExecutionUtils .getPage (result instanceof List ? (List <T >) result : new ArrayList <>(result ),
208
+ pageable , countSupplier );
209
+ }
210
+
211
+ }
107
212
}
0 commit comments