-
Notifications
You must be signed in to change notification settings - Fork 161
/
NamedStoredProcedureQueryMetadata.java
376 lines (322 loc) · 12.4 KB
/
NamedStoredProcedureQueryMetadata.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
/*
* Copyright (c) 1998, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
// 05/16/2008-1.0M8 Guy Pelletier
// - 218084: Implement metadata merging functionality between mapping files
// 03/24/2011-2.3 Guy Pelletier
// - 337323: Multi-tenant with shared schema support (part 1)
// 02/08/2012-2.4 Guy Pelletier
// - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
// 06/20/2012-2.5 Guy Pelletier
// - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
// 08/24/2012-2.5 Guy Pelletier
// - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
// 08/11/2012-2.5 Guy Pelletier
// - 393867: Named queries do not work when using EM level Table Per Tenant Multitenancy.
// 11/19/2012-2.5 Guy Pelletier
// - 389090: JPA 2.1 DDL Generation Support (foreign key metadata support)
package org.eclipse.persistence.internal.jpa.metadata.queries;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.persistence.internal.jpa.JPAQuery;
import org.eclipse.persistence.internal.jpa.metadata.accessors.MetadataAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAccessibleObject;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAnnotation;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataClass;
import org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappings;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.queries.StoredProcedureCall;
/**
* INTERNAL:
* Object to hold onto a named stored procedure query.
* <p>
* Key notes:
* - any metadata mapped from XML to this class must be compared in the
* equals method.
* - all metadata mapped from XML should be initialized in the initXMLObject
* method.
* - when loading from annotations, the constructor accepts the metadata
* accessor this metadata was loaded from. Used it to look up any
* 'companion' annotation needed for processing.
* - methods should be preserved in alphabetical order.
*
* @author Guy Pelletier
* @since TopLink 11g
*/
public class NamedStoredProcedureQueryMetadata extends NamedNativeQueryMetadata {
private Boolean m_multipleResultSets;
private Boolean m_returnsResultSet;
private Boolean m_callByIndex;
private List<MetadataClass> m_resultClasses = new ArrayList<>();
private List<String> m_resultClassNames = new ArrayList<>();
private List<String> m_resultSetMappings = new ArrayList<>();
private List<StoredProcedureParameterMetadata> m_parameters = new ArrayList<>();
private String m_procedureName;
/**
* INTERNAL:
* Used for XML loading.
*/
public NamedStoredProcedureQueryMetadata() {
super("<named-stored-procedure-query>");
}
/**
* INTERNAL:
*/
public NamedStoredProcedureQueryMetadata(MetadataAnnotation namedStoredProcedureQuery, MetadataAccessor accessor) {
super(namedStoredProcedureQuery, accessor);
for (Object storedProcedureParameter : namedStoredProcedureQuery.getAttributeArray("parameters")) {
m_parameters.add(new StoredProcedureParameterMetadata((MetadataAnnotation)storedProcedureParameter, accessor));
}
// JPA spec allows for multiple result classes.
for (Object resultClass : namedStoredProcedureQuery.getAttributeArray("resultClasses")) {
m_resultClasses.add(getMetadataClass((String) resultClass));
}
// JPA spec allows for multiple result set mappings.
for (Object resultSetMapping : namedStoredProcedureQuery.getAttributeArray("resultSetMappings")) {
m_resultSetMappings.add((String) resultSetMapping);
}
m_procedureName = namedStoredProcedureQuery.getAttributeString("procedureName");
// Don't default these booleans as we want to know if the user has actually set them.
m_returnsResultSet = namedStoredProcedureQuery.getAttributeBooleanDefaultFalse("returnsResultSet");
m_multipleResultSets = namedStoredProcedureQuery.getAttributeBooleanDefaultFalse("multipleResultSets");
m_callByIndex = namedStoredProcedureQuery.getAttributeBooleanDefaultFalse("callByIndex");
}
/**
* INTERNAL:
* Used for XML loading.
*/
public NamedStoredProcedureQueryMetadata(String elementName) {
super(elementName);
}
/**
* INTERNAL:
*/
public boolean callByIndex() {
return m_callByIndex != null && m_callByIndex;
}
/**
* INTERNAL:
*/
@Override
public boolean equals(Object objectToCompare) {
if (super.equals(objectToCompare) && objectToCompare instanceof NamedStoredProcedureQueryMetadata query) {
if (! valuesMatch(m_returnsResultSet, query.getReturnsResultSet())) {
return false;
}
if (! valuesMatch(m_callByIndex, query.getCallByIndex())) {
return false;
}
if (! valuesMatch(m_multipleResultSets, query.getMultipleResultSets())) {
return false;
}
if (! valuesMatch(m_parameters, query.getParameters())) {
return false;
}
if (! valuesMatch(m_resultClassNames, query.getResultClassNames())) {
return false;
}
if (! valuesMatch(m_resultSetMappings, query.getResultSetMappings())) {
return false;
}
return valuesMatch(m_procedureName, query.getProcedureName());
}
return false;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (m_multipleResultSets != null ? m_multipleResultSets.hashCode() : 0);
result = 31 * result + (m_returnsResultSet != null ? m_returnsResultSet.hashCode() : 0);
result = 31 * result + (m_callByIndex != null ? m_callByIndex.hashCode() : 0);
result = 31 * result + (m_resultClassNames != null ? m_resultClassNames.hashCode() : 0);
result = 31 * result + (m_resultSetMappings != null ? m_resultSetMappings.hashCode() : 0);
result = 31 * result + (m_parameters != null ? m_parameters.hashCode() : 0);
result = 31 * result + (m_procedureName != null ? m_procedureName.hashCode() : 0);
return result;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public Boolean getCallByIndex() {
return m_callByIndex;
}
/**
* INTERNAL:
* Used for OX mapping
*/
public Boolean getMultipleResultSets() {
return m_multipleResultSets;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public List<StoredProcedureParameterMetadata> getParameters() {
return m_parameters;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public String getProcedureName() {
return m_procedureName;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public List<String> getResultClassNames() {
return m_resultClassNames;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public List<String> getResultSetMappings() {
return m_resultSetMappings;
}
/**
* INTERNAL:
* Used for OX mapping
*/
public Boolean getReturnsResultSet() {
return m_returnsResultSet;
}
/**
* INTERNAL:
* If there is no user setting and there are not multiple result classes
* or result set mappings, assume a single result is returned. There is no
* way to set this parameter via JPA, only through EclipseLink's metadata.
*/
public boolean hasMultipleResultSets() {
return m_multipleResultSets == null ? (m_resultClasses.size() > 1 || m_resultSetMappings.size() > 1) : m_multipleResultSets;
}
/**
* INTERNAL:
*/
@Override
public void initXMLObject(MetadataAccessibleObject accessibleObject, XMLEntityMappings entityMappings) {
super.initXMLObject(accessibleObject, entityMappings);
// Initialize parameters ...
initXMLObjects(m_parameters, accessibleObject);
// Initialize all the result class names into MetadataClass.
for (String resultClassName : m_resultClassNames) {
m_resultClasses.add(initXMLClassName(resultClassName));
}
}
/**
* INTERNAL:
*/
@Override
public void process(AbstractSession session) {
// Build the stored procedure call.
StoredProcedureCall call = new StoredProcedureCall();
// Process the stored procedure parameters.
int index = 1;
boolean callByIndex = callByIndex();
boolean hasOutParameters = false;
for (StoredProcedureParameterMetadata parameter : m_parameters) {
parameter.processArgument(call, callByIndex, index);
index++;
// In JPA, if we have at least one out parameter we assume the
// procedure does not return a result set.
if (parameter.isOutParameter()) {
hasOutParameters = true;
}
}
// Process the procedure name.
call.setProcedureName(m_procedureName);
// Process the returns result set.
call.setReturnsResultSet(returnsResultSet(hasOutParameters));
// Process the multiple result sets.
call.setHasMultipleResultSets(hasMultipleResultSets());
// Create a JPA query to store internally on the session.
JPAQuery query = new JPAQuery(getName(), call, processQueryHints(session));
if (! m_resultClasses.isEmpty()) {
// Process the multiple result classes.
for (MetadataClass resultClass : m_resultClasses) {
query.addResultClassNames(getJavaClassName(resultClass));
}
} else if (! m_resultSetMappings.isEmpty()) {
// Process the multiple result set mapping.
query.setResultSetMappings(m_resultSetMappings);
} else {
// Legacy support (EclipseLink @NamedStoreProcedureQuery).
if (!getResultClass().isVoid()) {
query.setResultClassName(getJavaClassName(getResultClass()));
} else if (hasResultSetMapping(session)) {
query.addResultSetMapping(getResultSetMapping());
}
}
addJPAQuery(query, session);
}
/**
* INTERNAL:
* If there is no user setting and there are no out parameters, assume
* a result set is returned. There is no way to set this parameter via
* JPA, only through EclipseLink's metadata.
*/
public boolean returnsResultSet(boolean hasOutParameters) {
return m_returnsResultSet == null ? (!hasOutParameters) : m_returnsResultSet;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setCallByIndex(Boolean callByIndex) {
m_callByIndex = callByIndex;
}
/**
* INTERNAL:
* Used for OX mapping
*/
public void setMultipleResultSets(Boolean multipleResultSets) {
m_multipleResultSets = multipleResultSets;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setParameters(List<StoredProcedureParameterMetadata> parameters) {
m_parameters = parameters;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setProcedureName(String procedureName) {
m_procedureName = procedureName;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setResultClassNames(List<String> resultClassNames) {
m_resultClassNames = resultClassNames;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setResultSetMappings(List<String> resultSetMappings) {
m_resultSetMappings = resultSetMappings;
}
/**
* INTERNAL:
* Used for OX mapping.
*/
public void setReturnsResultSet(Boolean returnsResultSet) {
m_returnsResultSet = returnsResultSet;
}
}