15
15
*/
16
16
package org .springframework .data .jdbc .repository .query ;
17
17
18
+ import static org .springframework .data .jdbc .repository .query .JdbcQueryExecution .*;
19
+
18
20
import java .sql .ResultSet ;
19
21
import java .util .ArrayList ;
20
22
import java .util .Collection ;
21
23
import java .util .List ;
22
24
import java .util .function .LongSupplier ;
23
25
26
+ import org .springframework .core .convert .converter .Converter ;
24
27
import org .springframework .data .domain .Pageable ;
25
28
import org .springframework .data .domain .Slice ;
26
29
import org .springframework .data .domain .SliceImpl ;
32
35
import org .springframework .data .relational .repository .query .RelationalParameterAccessor ;
33
36
import org .springframework .data .relational .repository .query .RelationalParametersParameterAccessor ;
34
37
import org .springframework .data .repository .query .Parameters ;
38
+ import org .springframework .data .repository .query .ResultProcessor ;
39
+ import org .springframework .data .repository .query .ReturnedType ;
35
40
import org .springframework .data .repository .query .parser .PartTree ;
36
41
import org .springframework .data .support .PageableExecutionUtils ;
37
42
import org .springframework .jdbc .core .ResultSetExtractor ;
@@ -53,9 +58,8 @@ public class PartTreeJdbcQuery extends AbstractJdbcQuery {
53
58
private final Parameters <?, ?> parameters ;
54
59
private final Dialect dialect ;
55
60
private final JdbcConverter converter ;
61
+ private final RowMapperFactory rowMapperFactory ;
56
62
private final PartTree tree ;
57
- /** The execution for obtaining the bulk of the data. The execution may be decorated with further processing for handling sliced or paged queries */
58
- private final JdbcQueryExecution <?> coreExecution ;
59
63
60
64
/**
61
65
* Creates a new {@link PartTreeJdbcQuery}.
@@ -69,26 +73,40 @@ public class PartTreeJdbcQuery extends AbstractJdbcQuery {
69
73
*/
70
74
public PartTreeJdbcQuery (RelationalMappingContext context , JdbcQueryMethod queryMethod , Dialect dialect ,
71
75
JdbcConverter converter , NamedParameterJdbcOperations operations , RowMapper <Object > rowMapper ) {
76
+ this (context , queryMethod , dialect , converter , operations , it -> rowMapper );
77
+ }
78
+
79
+ /**
80
+ * Creates a new {@link PartTreeJdbcQuery}.
81
+ *
82
+ * @param context must not be {@literal null}.
83
+ * @param queryMethod must not be {@literal null}.
84
+ * @param dialect must not be {@literal null}.
85
+ * @param converter must not be {@literal null}.
86
+ * @param operations must not be {@literal null}.
87
+ * @param rowMapperFactory must not be {@literal null}.
88
+ * @since 2.3
89
+ */
90
+ public PartTreeJdbcQuery (RelationalMappingContext context , JdbcQueryMethod queryMethod , Dialect dialect ,
91
+ JdbcConverter converter , NamedParameterJdbcOperations operations , RowMapperFactory rowMapperFactory ) {
72
92
73
- super (queryMethod , operations , rowMapper );
93
+ super (queryMethod , operations );
74
94
75
95
Assert .notNull (context , "RelationalMappingContext must not be null" );
76
96
Assert .notNull (queryMethod , "JdbcQueryMethod must not be null" );
77
97
Assert .notNull (dialect , "Dialect must not be null" );
78
98
Assert .notNull (converter , "JdbcConverter must not be null" );
99
+ Assert .notNull (rowMapperFactory , "RowMapperFactory must not be null" );
79
100
80
101
this .context = context ;
81
102
this .parameters = queryMethod .getParameters ();
82
103
this .dialect = dialect ;
83
104
this .converter = converter ;
105
+ this .rowMapperFactory = rowMapperFactory ;
84
106
85
107
this .tree = new PartTree (queryMethod .getName (), queryMethod .getEntityInformation ().getJavaType ());
86
108
JdbcQueryCreator .validate (this .tree , this .parameters , this .converter .getMappingContext ());
87
109
88
- ResultSetExtractor <Boolean > extractor = tree .isExistsProjection () ? (ResultSet ::next ) : null ;
89
-
90
- this .coreExecution = queryMethod .isPageQuery () || queryMethod .isSliceQuery () ? collectionQuery (rowMapper )
91
- : getQueryExecution (queryMethod , extractor , rowMapper );
92
110
}
93
111
94
112
private Sort getDynamicSort (RelationalParameterAccessor accessor ) {
@@ -104,30 +122,48 @@ public Object execute(Object[] values) {
104
122
105
123
RelationalParametersParameterAccessor accessor = new RelationalParametersParameterAccessor (getQueryMethod (),
106
124
values );
107
- ParametrizedQuery query = createQuery (accessor );
108
- JdbcQueryExecution <?> execution = getDecoratedExecution (accessor );
125
+
126
+ ResultProcessor processor = getQueryMethod ().getResultProcessor ().withDynamicProjection (accessor );
127
+ ParametrizedQuery query = createQuery (accessor , processor .getReturnedType ());
128
+ JdbcQueryExecution <?> execution = getQueryExecution (processor , accessor );
109
129
110
130
return execution .execute (query .getQuery (), query .getParameterSource ());
111
131
}
112
132
113
- /**
114
- * The decorated execution is the {@link #coreExecution} decorated with further processing for handling sliced or paged queries.
115
- */
116
- private JdbcQueryExecution <?> getDecoratedExecution (RelationalParametersParameterAccessor accessor ) {
133
+ private JdbcQueryExecution <?> getQueryExecution (ResultProcessor processor ,
134
+ RelationalParametersParameterAccessor accessor ) {
135
+
136
+ ResultSetExtractor <Boolean > extractor = tree .isExistsProjection () ? (ResultSet ::next ) : null ;
137
+
138
+ RowMapper <Object > rowMapper ;
139
+
140
+ if (tree .isCountProjection () || tree .isExistsProjection ()) {
141
+ rowMapper = rowMapperFactory .create (resolveTypeToRead (processor ));
142
+ } else {
143
+
144
+ Converter <Object , Object > resultProcessingConverter = new ResultProcessingConverter (processor ,
145
+ this .converter .getMappingContext (), this .converter .getEntityInstantiators ());
146
+ rowMapper = new ConvertingRowMapper <>(rowMapperFactory .create (processor .getReturnedType ().getDomainType ()),
147
+ resultProcessingConverter );
148
+ }
149
+
150
+ JdbcQueryExecution <?> queryExecution = getQueryMethod ().isPageQuery () || getQueryMethod ().isSliceQuery ()
151
+ ? collectionQuery (rowMapper )
152
+ : getQueryExecution (getQueryMethod (), extractor , rowMapper );
117
153
118
154
if (getQueryMethod ().isSliceQuery ()) {
119
- return new SliceQueryExecution <>((JdbcQueryExecution <Collection <Object >>) this . coreExecution , accessor .getPageable ());
155
+ return new SliceQueryExecution <>((JdbcQueryExecution <Collection <Object >>) queryExecution , accessor .getPageable ());
120
156
}
121
157
122
158
if (getQueryMethod ().isPageQuery ()) {
123
159
124
- return new PageQueryExecution <>((JdbcQueryExecution <Collection <Object >>) this . coreExecution , accessor .getPageable (),
160
+ return new PageQueryExecution <>((JdbcQueryExecution <Collection <Object >>) queryExecution , accessor .getPageable (),
125
161
() -> {
126
162
127
163
RelationalEntityMetadata <?> entityMetadata = getQueryMethod ().getEntityInformation ();
128
164
129
165
JdbcCountQueryCreator queryCreator = new JdbcCountQueryCreator (context , tree , converter , dialect ,
130
- entityMetadata , accessor , false );
166
+ entityMetadata , accessor , false , processor . getReturnedType () );
131
167
132
168
ParametrizedQuery countQuery = queryCreator .createQuery (Sort .unsorted ());
133
169
Object count = singleObjectQuery ((rs , i ) -> rs .getLong (1 )).execute (countQuery .getQuery (),
@@ -137,15 +173,15 @@ private JdbcQueryExecution<?> getDecoratedExecution(RelationalParametersParamete
137
173
});
138
174
}
139
175
140
- return this . coreExecution ;
176
+ return queryExecution ;
141
177
}
142
178
143
- protected ParametrizedQuery createQuery (RelationalParametersParameterAccessor accessor ) {
179
+ protected ParametrizedQuery createQuery (RelationalParametersParameterAccessor accessor , ReturnedType returnedType ) {
144
180
145
181
RelationalEntityMetadata <?> entityMetadata = getQueryMethod ().getEntityInformation ();
146
182
147
183
JdbcQueryCreator queryCreator = new JdbcQueryCreator (context , tree , converter , dialect , entityMetadata , accessor ,
148
- getQueryMethod ().isSliceQuery ());
184
+ getQueryMethod ().isSliceQuery (), returnedType );
149
185
return queryCreator .createQuery (getDynamicSort (accessor ));
150
186
}
151
187
0 commit comments