23
23
import javax .persistence .EntityManager ;
24
24
import javax .persistence .NamedStoredProcedureQuery ;
25
25
import javax .persistence .ParameterMode ;
26
+ import javax .persistence .StoredProcedureParameter ;
26
27
import javax .persistence .StoredProcedureQuery ;
27
28
import javax .persistence .TypedQuery ;
28
29
@@ -132,42 +133,32 @@ Object extractOutputValue(StoredProcedureQuery storedProcedureQuery) {
132
133
return null ;
133
134
}
134
135
135
- Map <String , Object > outputValues = new HashMap <>();
136
- List <String > parameterNames = procedureAttributes .getOutputParameterNames ();
137
-
138
- for (int i = 0 ; i < parameterNames .size (); i ++) {
136
+ List <ProcedureParameter > outputParameters = procedureAttributes .getOutputProcedureParameters ();
139
137
140
- String name = parameterNames . get ( i );
141
- outputValues . put ( name , extractOutputParameter ( storedProcedureQuery , i ) );
138
+ if ( outputParameters . size () == 1 ) {
139
+ return extractOutputParameterValue ( outputParameters . get ( 0 ), 0 , storedProcedureQuery );
142
140
}
143
141
144
- return outputValues .size () == 1 ? outputValues .values ().iterator ().next () : outputValues ;
145
- }
146
-
147
- private Object extractOutputParameter (StoredProcedureQuery storedProcedureQuery , Integer index ) {
142
+ Map <String , Object > outputValues = new HashMap <>();
148
143
149
- String outputParameterName = procedureAttributes .getOutputParameterNames ().get (index );
150
- JpaParameters parameters = getQueryMethod ().getParameters ();
144
+ for (int i = 0 ; i < outputParameters .size (); i ++) {
145
+ ProcedureParameter outputParameter = outputParameters .get (i );
146
+ outputValues .put (outputParameter .getName (), extractOutputParameterValue (outputParameter , i , storedProcedureQuery ));
147
+ }
151
148
152
- return extractOutputParameterValue (storedProcedureQuery , outputParameterName , index ,
153
- parameters .getNumberOfParameters ());
149
+ return outputValues ;
154
150
}
155
151
156
152
/**
157
- * extract the value of an output parameter either by name or by index.
158
- *
159
- * @param storedProcedureQuery the query object of the stored procedure.
160
- * @param name the name of the output parameter
161
- * @param index index of the output parameter
162
- * @param offset for index based access the index after which to find the output parameter values
163
- * @return the value
153
+ * @return The value of an output parameter either by name or by index.
164
154
*/
165
- private Object extractOutputParameterValue (StoredProcedureQuery storedProcedureQuery , String name , Integer index ,
166
- int offset ) {
155
+ private Object extractOutputParameterValue (ProcedureParameter outputParameter , Integer index , StoredProcedureQuery storedProcedureQuery ) {
156
+
157
+ JpaParameters methodParameters = getQueryMethod ().getParameters ();
167
158
168
- return useNamedParameters && StringUtils .hasText (name ) ? //
169
- storedProcedureQuery .getOutputParameterValue (name )
170
- : storedProcedureQuery .getOutputParameterValue (offset + index + 1 );
159
+ return useNamedParameters && StringUtils .hasText (outputParameter . getName ()) ?
160
+ storedProcedureQuery .getOutputParameterValue (outputParameter . getName () )
161
+ : storedProcedureQuery .getOutputParameterValue (methodParameters . getNumberOfParameters () + index + 1 );
171
162
}
172
163
173
164
/**
@@ -192,9 +183,7 @@ private StoredProcedureQuery newNamedStoredProcedureQuery() {
192
183
private StoredProcedureQuery newAdhocStoredProcedureQuery () {
193
184
194
185
JpaParameters params = getQueryMethod ().getParameters ();
195
- String procedureName = procedureAttributes .getProcedureName ();
196
-
197
- StoredProcedureQuery procedureQuery = getEntityManager ().createStoredProcedureQuery (procedureName );
186
+ StoredProcedureQuery procedureQuery = createAdhocStoredProcedureQuery ();
198
187
199
188
for (JpaParameter param : params ) {
200
189
@@ -214,23 +203,41 @@ private StoredProcedureQuery newAdhocStoredProcedureQuery() {
214
203
215
204
if (procedureAttributes .hasReturnValue ()) {
216
205
217
- ParameterMode mode = ParameterMode . OUT ;
206
+ ProcedureParameter procedureOutput = procedureAttributes . getOutputProcedureParameters (). get ( 0 ) ;
218
207
219
- IntStream .range (0 , procedureAttributes .getOutputParameterTypes ().size ()).forEach (i -> {
220
- Class <?> outputParameterType = procedureAttributes .getOutputParameterTypes ().get (i );
208
+ /* If the stored procedure returns a ResultSet without using REF_CURSOR,
209
+ it is not necessary to declare an output parameter */
210
+ if ((isResultSetProcedure () && procedureOutput .getMode () == ParameterMode .REF_CURSOR ) || !isResultSetProcedure ()) {
221
211
222
212
if (useNamedParameters ) {
223
-
224
- String outputParameterName = procedureAttributes .getOutputParameterNames ().get (i );
225
- procedureQuery .registerStoredProcedureParameter (outputParameterName , outputParameterType , mode );
226
-
213
+ procedureQuery .registerStoredProcedureParameter (procedureOutput .getName (), procedureOutput .getType (), procedureOutput .getMode ());
227
214
} else {
228
- procedureQuery .registerStoredProcedureParameter (params .getNumberOfParameters () + i + 1 , outputParameterType ,
229
- mode );
215
+ // Output parameter should be after the input parameters
216
+ int outputParameterIndex = params .getNumberOfParameters () + 1 ;
217
+ procedureQuery .registerStoredProcedureParameter (outputParameterIndex , procedureOutput .getType (),
218
+ procedureOutput .getMode ());
230
219
}
231
- });
220
+ }
232
221
}
233
222
234
223
return procedureQuery ;
235
224
}
225
+
226
+ private StoredProcedureQuery createAdhocStoredProcedureQuery () {
227
+ String procedureName = procedureAttributes .getProcedureName ();
228
+
229
+ if (getQueryMethod ().isQueryForEntity ()) {
230
+ return getEntityManager ().createStoredProcedureQuery (procedureName ,
231
+ getQueryMethod ().getEntityInformation ().getJavaType ());
232
+ }
233
+
234
+ return getEntityManager ().createStoredProcedureQuery (procedureName );
235
+ }
236
+
237
+ /**
238
+ * @return true if the stored procedure will use a ResultSet to return data and not output parameters
239
+ */
240
+ private boolean isResultSetProcedure () {
241
+ return getQueryMethod ().isCollectionQuery () || getQueryMethod ().isQueryForEntity ();
242
+ }
236
243
}
0 commit comments