KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > descriptors > DescriptorQueryManager


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2006, Oracle. All rights reserved.
22
package oracle.toplink.essentials.descriptors;
23
24 import java.util.*;
25 import java.io.*;
26 import oracle.toplink.essentials.queryframework.*;
27 import oracle.toplink.essentials.expressions.*;
28 import oracle.toplink.essentials.mappings.*;
29 import oracle.toplink.essentials.sessions.DatabaseRecord;
30 import oracle.toplink.essentials.internal.helper.*;
31 import oracle.toplink.essentials.exceptions.*;
32 import oracle.toplink.essentials.descriptors.InheritancePolicy;
33 import oracle.toplink.essentials.internal.sessions.AbstractSession;
34
35 /**
36  * <p><b>Purpose</b>: The query manager allows for the database opperations that TopLink
37  * performs to be customized by the application. For each descriptor a query can be
38  * given that controls how a operation will occur. A common example is if the application
39  * requires a stored procedure to be used to insert the object, it can override the SQL call
40  * in the insert query that TopLink will use to insert the object.
41  * Queries can be customized to extend TopLink behavior, access non-relational data or use stored
42  * procedures or customized SQL calls.
43  * <p>
44  * The queries that can be customized include:
45  * <ul>
46  * <li> insertQuery - used to insert the object
47  * <li> updateQuery - used to update the object
48  * <li> readObjectQuery - used to read a single object by primary key
49  * <li> readAllQuery - used to read all of the objects of the class
50  * <li> doesExistQuery - used to determine whether an insert or update should occur
51  * <li> deleteQuery - used to delete the object
52  * </ul>
53  *
54  * @see ClassDescriptor
55  */

56 public class DescriptorQueryManager implements Cloneable JavaDoc, Serializable {
57     protected transient InsertObjectQuery insertQuery;
58     protected transient UpdateObjectQuery updateQuery;
59     protected transient ReadObjectQuery readObjectQuery;
60     protected transient ReadAllQuery readAllQuery;
61     protected transient DeleteObjectQuery deleteQuery;
62     protected DoesExistQuery doesExistQuery;
63     protected ClassDescriptor descriptor;
64     protected boolean hasCustomMultipleTableJoinExpression;
65     protected transient Expression additionalJoinExpression;
66     protected transient Expression multipleTableJoinExpression;
67     protected transient Map queries;
68     protected transient Map tablesJoinExpressions;
69
70     /**
71      * INTERNAL:
72      * Initialize the state of the descriptor query manager
73      */

74     public DescriptorQueryManager() {
75         this.queries = new HashMap(5);
76         setDoesExistQuery(new DoesExistQuery());// Always has a does exist.
77
}
78
79     /**
80      * PUBLIC:
81      * Add the query to the descriptor queries with the given name
82      * @param name This is the name of the query. It will be set on the query and used to look it up.
83      * @param query This is the query that will be added. If the query being added has parameters, the
84      * existing list of queries will be checked for matching queries. If a matching query exists,
85      * it will be replaced.
86      */

87     public void addQuery(String JavaDoc name, DatabaseQuery query) {
88         query.setName(name);
89         addQuery(query);
90     }
91
92     /**
93      * PUBLIC:
94      * Add the query to the session queries
95      * @param query DatabaseQuery This is the query that will be added. If the query being added has parameters, the
96      * existing list of queries will be checked for matching queries. If a matching query exists,
97      * it will be replaced.
98      */

99     public synchronized void addQuery(DatabaseQuery query) {
100         if (query instanceof ObjectLevelReadQuery && (((ObjectLevelReadQuery)query).getReferenceClassName() == null)) {
101             ((ObjectLevelReadQuery)query).setReferenceClassName(getDescriptor().getJavaClassName());
102
103             // try to set the reference ClassNotFoundException since it should only happen on the MW in which
104
// case we will lazily initialize the reference class at a later point.
105
try {
106                 ((ObjectLevelReadQuery)query).setReferenceClass(getDescriptor().getJavaClass());
107             } catch (ConversionException exception) {
108             }
109
110             //this is an optimization
111
query.setDescriptor(getDescriptor());
112         }
113
114         // Add query has been synchronized for bug 3355199.
115
// Additionally code has been added to ensure that the same query is not added twice.
116
Vector queriesByName = (Vector)getQueries().get(query.getName());
117         if (queriesByName == null) {
118             // lazily create Vector in Hashtable.
119
queriesByName = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance();
120             getQueries().put(query.getName(), queriesByName);
121         } else {
122             int argumentTypesSize = 0;
123             if (query.getArguments() != null) {
124                 argumentTypesSize = query.getArguments().size();
125             }
126             Vector argumentTypes = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(argumentTypesSize);
127             for (int i = 0; i < argumentTypesSize; i++) {
128                 argumentTypes.addElement(query.getArgumentTypeNames().elementAt(i));
129             }
130
131             // Search for a query with the same parameters and replace it if one is found
132
for (int i = 0; i < queriesByName.size(); i++) {
133                 DatabaseQuery currentQuery = (DatabaseQuery)queriesByName.elementAt(i);
134
135                 // Here we are checking equality instead of assignability. If you look at getQuery()
136
// it is the other way around.
137
// The reason we do this is we are replacing a query and we want to make sure we are
138
// replacing the exact same one. - TW
139
if (argumentTypes.equals(currentQuery.getArgumentTypeNames())) {
140                     queriesByName.remove(i);
141                     queriesByName.add(i, query);
142                     return;
143                 }
144             }
145         }
146         queriesByName.add(query);
147     }
148
149     /**
150      * PUBLIC:
151      * Assume that if the objects primary key does not include null then it must exist.
152      * This may be used if the application guarantees or does not care about the existence check.
153      */

154     public void assumeExistenceForDoesExist() {
155         getDoesExistQuery().assumeExistenceForDoesExist();
156     }
157
158     /**
159      * PUBLIC:
160      * Assume that the object does not exist. This may be used if the application guarantees or
161      * does not care about the existence check. This will always force an insert to be called.
162      */

163     public void assumeNonExistenceForDoesExist() {
164         getDoesExistQuery().assumeNonExistenceForDoesExist();
165     }
166
167     /**
168      * PUBLIC:
169      * Default behavior.
170      * Assume that if the objects primary key does not include null and it
171      * is in the cache, then is must exist.
172      */

173     public void checkCacheForDoesExist() {
174         getDoesExistQuery().checkCacheForDoesExist();
175     }
176
177     /**
178      * PUBLIC:
179      * Perform does exist check on the database
180      */

181     public void checkDatabaseForDoesExist() {
182         getDoesExistQuery().checkDatabaseForDoesExist();
183     }
184
185     /**
186      * INTERNAL:
187      * Clone the query manager
188      */

189     public Object JavaDoc clone() {
190         DescriptorQueryManager manager = null;
191         try {
192             manager = (DescriptorQueryManager)super.clone();
193         } catch (Exception JavaDoc exception) {
194             ;
195         }
196
197         // Bug 3037701 - clone the queries
198
manager.setQueries(new Hashtable(getQueries().size()));
199         Iterator iterator = queries.values().iterator();
200         while (iterator.hasNext()) {
201             Iterator queriesForKey = ((Vector)iterator.next()).iterator();
202             while (queriesForKey.hasNext()) {
203                 DatabaseQuery initialQuery = (DatabaseQuery)queriesForKey.next();
204                 DatabaseQuery clonedQuery = (DatabaseQuery)initialQuery.clone();
205                 clonedQuery.setDescriptor(manager.getDescriptor());
206                 manager.addQuery(clonedQuery);
207             }
208         }
209         manager.setDoesExistQuery((DoesExistQuery)getDoesExistQuery().clone());
210         if (getReadAllQuery() != null) {
211             manager.setReadAllQuery((ReadAllQuery)getReadAllQuery().clone());
212         }
213         if (getReadObjectQuery() != null) {
214             manager.setReadObjectQuery((ReadObjectQuery)getReadObjectQuery().clone());
215         }
216         if (getUpdateQuery() != null) {
217             manager.setUpdateQuery((UpdateObjectQuery)getUpdateQuery().clone());
218         }
219         if (getInsertQuery() != null) {
220             manager.setInsertQuery((InsertObjectQuery)getInsertQuery().clone());
221         }
222         if (getDeleteQuery() != null) {
223             manager.setDeleteQuery((DeleteObjectQuery)getDeleteQuery().clone());
224         }
225
226         return manager;
227     }
228
229     /**
230      * PUBLIC:
231      * Return true if the query is defined on the session
232      */

233     public boolean containsQuery(String JavaDoc queryName) {
234         return queries.containsKey(queryName);
235     }
236
237     /**
238      * INTERNAL:
239      * Convert all the class-name-based settings in this Query Manager to actual class-based
240      * settings
241      * This method is implemented by subclasses as necessary.
242      * @param classLoader
243      */

244     public void convertClassNamesToClasses(ClassLoader JavaDoc classLoader){
245         Iterator queryVectors = getQueries().values().iterator();
246         while (queryVectors.hasNext()){
247             Iterator queries = ((Vector)queryVectors.next()).iterator();;
248             while (queries.hasNext()){
249                 ((DatabaseQuery)queries.next()).convertClassNamesToClasses(classLoader);
250             }
251         }
252     };
253
254     /**
255      * ADVANCED:
256      * Returns the join expression that should be appended to all of the descriptors expressions
257      * Contains any multiple table or inheritance dependencies
258      */

259     public Expression getAdditionalJoinExpression() {
260         return additionalJoinExpression;
261     }
262
263     /**
264      * ADVANCED:
265      * Return the receiver's delete query.
266      * This should be an instance of a valid subclass of DeleteObjectQuery.
267      * If specified this is used by the descriptor to delete itself and its private parts from the database.
268      * This gives the user the ability to define exactly how to delete the data from the database,
269      * or access data external from the database or from some other framework.
270      */

271     public DeleteObjectQuery getDeleteQuery() {
272         return deleteQuery;
273     }
274
275     /**
276      * ADVANCED:
277      * Return the receiver's delete SQL string.
278      * This allows the user to override the SQL generated by TopLink, with their own SQL or procedure call.
279      * The arguments are translated from the fields of the source row,
280      * through replacing the field names marked by '#' with the values for those fields.
281      * <p>
282      * Example, "delete from EMPLOYEE where EMPLOYEE_ID = #EMPLOYEE_ID".
283      */

284     public String JavaDoc getDeleteSQLString() {
285         if (getDeleteQuery() == null) {
286             return null;
287         }
288
289         return getDeleteQuery().getSQLString();
290     }
291
292     /**
293      * INTERNAL:
294      * Return the descriptor associated with this descriptor query manager
295      */

296     protected ClassDescriptor getDescriptor() {
297         return descriptor;
298     }
299
300     /**
301      * ADVANCED:
302      * Return the receiver's does exist query.
303      * This should be an instance of a valid subclass of DoesExistQuery.
304      * If specified this is used by the descriptor to query existence of an object in the database.
305      * This gives the user the ability to define exactly how to query existence from the database,
306      * or access data external from the database or from some other framework.
307      */

308     public DoesExistQuery getDoesExistQuery() {
309         return doesExistQuery;
310     }
311
312     /**
313
314      * ADVANCED:
315      * Return the receiver's does exist SQL string.
316      * This allows the user to override the SQL generated by TopLink, with there own SQL or procedure call.
317      * The arguments are translated from the fields of the source row, through replacing the field names marked by '#'
318      * with the values for those fields.
319      * This must return null if the object does not exist, otherwise return a database row.
320      * <p>
321      * Example, "select EMPLOYEE_ID from EMPLOYEE where EMPLOYEE_ID = #EMPLOYEE_ID".
322      */

323     public String JavaDoc getDoesExistSQLString() {
324         if (getDoesExistQuery() == null) {
325             return null;
326         }
327
328         return getDoesExistQuery().getSQLString();
329     }
330
331     /**
332      * INTERNAL:
333      * This method is explicitly used by the Builder only.
334      */

335     public String JavaDoc getExistenceCheck() {
336         if (getDoesExistQuery().shouldAssumeExistenceForDoesExist()) {
337             return "Assume existence";
338         } else if (getDoesExistQuery().shouldAssumeNonExistenceForDoesExist()) {
339             return "Assume non-existence";
340         } else if (getDoesExistQuery().shouldCheckCacheForDoesExist()) {
341             return "Check cache";
342         } else if (getDoesExistQuery().shouldCheckDatabaseForDoesExist()) {
343             return "Check database";
344         } else {
345             // Default.
346
return "Check cache";
347         }
348     }
349
350     /**
351       * ADVANCED:
352       * Return the receiver's insert query.
353       * This should be an instance of a valid subclass of InsertObjectQuery.
354       * If specified this is used by the descriptor to insert itself into the database.
355       * If the receiver uses sequence numbers, this query must return the updated sequence value.
356       * This gives the user the ability to define exactly how to insert the data into the database,
357       * or access data externel from the database or from some other framework.
358       */

359     public InsertObjectQuery getInsertQuery() {
360         return insertQuery;
361     }
362
363     /**
364      * ADVANCED:
365      * Return the receiver's insert SQL string.
366      * This allows the user to override the SQL generated by TopLink, with their own SQL or procedure call.
367      * The arguments are translated from the fields of the source row,
368      * through replacing the field names marked by '#' with the values for those fields.
369      * <p>
370      * Example, "insert into EMPLOYEE (F_NAME, L_NAME) values (#F_NAME, #L_NAME)".
371      */

372     public String JavaDoc getInsertSQLString() {
373         if (getInsertQuery() == null) {
374             return null;
375         }
376
377         return getInsertQuery().getSQLString();
378     }
379
380     /**
381      * ADVANCED:
382      * This is normally generated for descriptors that have multiple tables.
383      * However, if the additional table does not reference the primary tables primary key,
384      * this expression may be set directly.
385      */

386     public Expression getMultipleTableJoinExpression() {
387         return multipleTableJoinExpression;
388     }
389
390     /**
391      * PUBLIC:
392      * Return the pre-defined queries for the descriptor. The Hashtable returned
393      * contains Vectors of queries.
394      *
395      * @see #getAllQueries()
396      */

397     public Map getQueries() {
398         return queries;
399     }
400
401     /**
402      * PUBLIC:
403      * Return the pre-defined queries for the descriptor. The Vector returned
404      * contains all queries for this descriptor.
405      *
406      * @see #getQueries()
407      */

408     public Vector getAllQueries() {
409         Vector allQueries = new Vector();
410         for (Iterator vectors = getQueries().values().iterator(); vectors.hasNext();) {
411             allQueries.addAll((Vector)vectors.next());
412         }
413         return allQueries;
414     }
415
416     /**
417      * INTERNAL:
418      * Set pre-defined queries for the descriptor. Converts the Vector to a hashtable
419      */

420     public void setAllQueries(Vector vector) {
421         for (Enumeration enumtr = vector.elements(); enumtr.hasMoreElements();) {
422             addQuery((DatabaseQuery)enumtr.nextElement());
423         }
424     }
425
426     /**
427      * PUBLIC:
428      * set the pre-defined queries for the descriptor. Used to write out deployment XML
429      */

430     public void setQueries(Map hashtable) {
431         queries = hashtable;
432     }
433
434     /**
435      * PUBLIC:
436      * Return the query name from the set of pre-defined queries
437      * If only one query exists with this name, it will be returned.
438      * If there are multiple queries of this name, this method will search for a query
439      * with no arguments and return the first one it finds.
440      *
441      * @see #getQuery(String, Vector)
442      */

443     public DatabaseQuery getQuery(String JavaDoc queryName) {
444         return getQuery(queryName, null);
445     }
446
447     /**
448      * PUBLIC:
449      * Return the query from the set of pre-defined queries with the given name and argument types.
450      * This allows for common queries to be pre-defined, reused and executed by name.
451      * This method should be used if the Session has multiple queries with the same name but
452      * different arguments.
453      * If only one query exists, it will be returned regardless of the arguments.
454      * If multiple queries exist, the first query that has corresponding argument types will be returned
455      *
456      * @see #getQuery(String)
457      */

458     public DatabaseQuery getQuery(String JavaDoc name, Vector arguments) {
459         DatabaseQuery query = getLocalQuery(name, arguments);
460
461         // CR#3711: Check if a query with the same name exists for this descriptor.
462
// If not, recursively check descriptors of parent classes. If nothing is
463
// found in parents, return null.
464
if (query == null) {
465             DatabaseQuery parentQuery = getQueryFromParent(name, arguments);
466             if (parentQuery != null && parentQuery.isReadQuery()) {
467                 parentQuery = (DatabaseQuery) parentQuery.clone();
468                 ((ObjectLevelReadQuery)parentQuery).setReferenceClass(getDescriptor().getJavaClass());
469                 addQuery(name, parentQuery);
470             }
471             return parentQuery;
472         }
473         return query;
474     }
475
476     /**
477      * INTENAL:
478      * Return the query from the set of pre-defined queries with the given name and argument types.
479      * This allows for common queries to be pre-defined, reused and executed by name.
480      * Only returns those queries locally defined, not superclass's queries
481      * If only one query exists, it will be returned regardless of the arguments.
482      * If multiple queries exist, the first query that has corresponding argument types will be returned
483      *
484      * @see #getQuery(String)
485      */

486     public DatabaseQuery getLocalQuery(String JavaDoc name, Vector arguments) {
487         Vector queries = (Vector)getQueries().get(name);
488
489         if (queries == null){
490             return null;
491         }
492         
493         // Short circuit the simple, most common case of only one query.
494
if (queries.size() == 1) {
495             return (DatabaseQuery)queries.firstElement();
496         }
497
498         // CR#3754; Predrag; mar 19/2002;
499
// We allow multiple named queries with the same name but
500
// different argument set; we can have only one query with
501
// no arguments; Vector queries is not sorted;
502
// When asked for the query with no parameters the
503
// old version did return the first query - wrong:
504
// return (DatabaseQuery) queries.firstElement();
505
int argumentTypesSize = 0;
506         if (arguments != null) {
507             argumentTypesSize = arguments.size();
508         }
509         Vector argumentTypes = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(argumentTypesSize);
510         for (int i = 0; i < argumentTypesSize; i++) {
511             argumentTypes.addElement(arguments.elementAt(i).getClass());
512         }
513         for (Enumeration queriesEnum = queries.elements(); queriesEnum.hasMoreElements();) {
514             DatabaseQuery query = (DatabaseQuery)queriesEnum.nextElement();
515
516             // BUG#2698755
517
// This check was backward, we default the type to Object
518
// Was checking Object is decendent of String not other way.
519
if (Helper.areTypesAssignable(query.getArgumentTypes(), argumentTypes)) {
520                 return query;
521             }
522         }
523
524         return null;
525
526     }
527
528     /**
529      * INTERNAL:
530      * CR#3711: Check if the class for this descriptor has a parent class.
531      * Then search this parent's descriptor for a query with the same name
532      * and arguments. If nothing found, return null.
533      *
534      * This method should only be used recursively by getQuery().
535      */

536     protected DatabaseQuery getQueryFromParent(String JavaDoc name, Vector arguments) {
537         ClassDescriptor descriptor = getDescriptor();
538         if (descriptor.hasInheritance()) {
539             InheritancePolicy inheritancePolicy = descriptor.getInheritancePolicy();
540             ClassDescriptor parent = inheritancePolicy.getParentDescriptor();
541
542             // if parent exists, check for the query
543
if (parent != null) {
544                 return parent.getQueryManager().getQuery(name, arguments);
545             }
546         }
547         return null;
548     }
549
550     /**
551       * ADVANCED:
552       * Return the receiver's read query.
553       * This should be an instance of a valid subclass of ReadAllQuery.
554       */

555     public ReadAllQuery getReadAllQuery() {
556         return readAllQuery;
557     }
558
559     /**
560      * ADVANCED:
561      * Return the receiver's read SQL string.
562      * This allows the user to override the SQL generated by TopLink, with their own SQL or procedure call.
563      * The arguments are translated from the fields of the read arguments row,
564      * through replacing the field names marked by '#' with the values for those fields.
565      * Note that this is only used on readAllObjects(Class), and not when an expression is provided.
566      * <p>
567      * Example, "select * from EMPLOYEE"
568      */

569     public String JavaDoc getReadAllSQLString() {
570         if (getReadAllQuery() == null) {
571             return null;
572         }
573
574         return getReadAllQuery().getSQLString();
575     }
576
577     /**
578      * ADVANCED:
579      * Return the receiver's read query.
580      * This should be an instance of a valid subclass of ReadObjectQuery.
581      * If specified this is used by the descriptor to read itself from the database.
582      * The read arguments must be the primary key of the object only.
583      * This gives the user the ability to define exactly how to read the object from the database,
584      * or access data externel from the database or from some other framework.
585      */

586     public ReadObjectQuery getReadObjectQuery() {
587         return readObjectQuery;
588     }
589
590     /**
591      * ADVANCED:
592      * Return the receiver's read SQL string.
593      * This allows the user to override the SQL generated by TopLink, with their own SQL or procedure call.
594      * The arguments are translated from the fields of the read arguments row,
595      * through replacing the field names marked by '#' with the values for those fields.
596      * This must accept only the primary key of the object as arguments.
597      * <p>
598      * Example, "select * from EMPLOYEE where EMPLOYEE_ID = #EMPLOYEE_ID"
599      */

600     public String JavaDoc getReadObjectSQLString() {
601         if (getReadObjectQuery() == null) {
602             return null;
603         }
604
605         return getReadObjectQuery().getSQLString();
606     }
607
608     /**
609       * ADVANCED:
610       * Return the receiver's update query.
611       * This should be an instance of a valid subclass of UpdateObjectQuery.
612       * If specified this is used by the descriptor to insert itself into the database.
613       * If the receiver uses optimisitic locking this must raise an error on optimisitic lock failure.
614       * This gives the user the ability to define exactly how to update the data into the database,
615       * or access data externel from the database or from some other framework.
616       */

617     public UpdateObjectQuery getUpdateQuery() {
618         return updateQuery;
619     }
620
621     /**
622      * ADVANCED:
623      * Return the receiver's update SQL string.
624      * This allows the user to override the SQL generated by TopLink, with there own SQL or procedure call.
625      * The arguments are translated from the fields of the source row,
626      * through replacing the field names marked by '#' with the values for those fields.
627      * This must check the optimistic lock field and raise an error on optimistic lock failure.
628      * <p>
629      * Example, "update EMPLOYEE set F_NAME to #F_NAME, L_NAME to #L_NAME where EMPLOYEE_ID = #EMPLOYEE_ID".
630      */

631     public String JavaDoc getUpdateSQLString() {
632         if (getUpdateQuery() == null) {
633             return null;
634         }
635
636         return getUpdateQuery().getSQLString();
637     }
638
639     /**
640      * INTERNAL:
641      * Return if a cutsom join expression is used.
642      */

643     public boolean hasCustomMultipleTableJoinExpression() {
644         return hasCustomMultipleTableJoinExpression;
645     }
646
647     /**
648      * INTERNAL:
649      * Flag that specifies if a delete query is available
650      */

651     public boolean hasDeleteQuery() {
652         return (deleteQuery != null);
653     }
654
655     /**
656      * INTERNAL:
657      * Flag that specifies if a does exist query is available
658      */

659     public boolean hasDoesExistQuery() {
660         return (doesExistQuery != null);
661     }
662
663     /**
664      * INTERNAL:
665      * Flag that specifies if a insert query is available
666      */

667     public boolean hasInsertQuery() {
668         return (insertQuery != null);
669     }
670
671     /**
672      * INTERNAL:
673      * Flag that specifies if a read all query is available
674      */

675     public boolean hasReadAllQuery() {
676         return (readAllQuery != null);
677     }
678
679     /**
680      * INTERNAL:
681      * Flag that specifies if a read object query is available
682      */

683     public boolean hasReadObjectQuery() {
684         return (readObjectQuery != null);
685     }
686
687     /**
688      * INTERNAL:
689      * Flag that specifies if a update query is available
690      */

691     public boolean hasUpdateQuery() {
692         return (updateQuery != null);
693     }
694
695     /**
696      * INTERNAL:
697      * populate the queries with the descriptor.
698      */

699     private void populateQueries() {
700
701         /* CR2260
702          * Descriptiron:
703          * NullPointerException accessing null descriptor
704          * Fix:
705          * Initialize queries with an instantiated descriptor at this point
706          */

707         if (getInsertQuery() != null) {
708             getInsertQuery().setDescriptor(descriptor);
709         }
710         if (getUpdateQuery() != null) {
711             getUpdateQuery().setDescriptor(descriptor);
712         }
713         if (getReadObjectQuery() != null) {
714             getReadObjectQuery().setReferenceClass(getDescriptor().getJavaClass());
715             getReadObjectQuery().setDescriptor(descriptor);
716         }
717         if (getDeleteQuery() != null) {
718             getDeleteQuery().setDescriptor(descriptor);
719         }
720         if (getReadAllQuery() != null) {
721             getReadAllQuery().setReferenceClass(getDescriptor().getJavaClass());
722             getReadAllQuery().setDescriptor(descriptor);
723         }
724         for (Iterator it = getAllQueries().iterator(); it.hasNext();) {
725             ((DatabaseQuery)it.next()).setDescriptor(descriptor);
726         }
727     }
728
729     /**
730      * INTERNAL:
731      * Post initialize the mappings
732      */

733     public void initialize(AbstractSession session) {
734
735         if (getDescriptor().isAggregateDescriptor()) {
736             return;
737         }
738
739         if (getMultipleTableJoinExpression() != null) {
740             // Combine new multiple table expression to additional join expression
741
setAdditionalJoinExpression(getMultipleTableJoinExpression().and(getAdditionalJoinExpression()));
742         }
743
744         if (getDescriptor().isAggregateCollectionDescriptor()) {
745             return;
746         }
747
748         //PERF: set read-object query to cache generated SQL.
749
if (!hasReadObjectQuery()) {
750             // Prepare static read object query always.
751
ReadObjectQuery readObjectQuery = new ReadObjectQuery();
752             readObjectQuery.setSelectionCriteria(getDescriptor().getObjectBuilder().getPrimaryKeyExpression());
753             setReadObjectQuery(readObjectQuery);
754         }
755         
756         if (!hasInsertQuery()) {
757             // Prepare insert query always.
758
setInsertQuery(new InsertObjectQuery());
759         }
760         getInsertQuery().setModifyRow(getDescriptor().getObjectBuilder().buildTemplateInsertRow(session));
761
762         if (!hasDeleteQuery()) {
763             // Prepare delete query always.
764
setDeleteQuery(new DeleteObjectQuery());
765         }
766         getDeleteQuery().setModifyRow(new DatabaseRecord());
767
768         if (hasUpdateQuery()) {
769             // Do not prepare to update by default to allow minimal update.
770
getUpdateQuery().setModifyRow(getDescriptor().getObjectBuilder().buildTemplateUpdateRow(session));
771         }
772     }
773
774     /**
775      * INTERNAL:
776      * Get the parent DescriptorQueryManager.
777      * Caution must be used in using this method as it expects the descriptor
778      * to have inheritance.
779      * Calling this when the descriptor that does not use inheritance will cause problems, #hasInheritance() must
780      * always first be called.
781      */

782     public DescriptorQueryManager getParentDescriptorQueryManager() {
783         return getDescriptor().getInheritancePolicy().getParentDescriptor().getQueryManager();
784     }
785
786     /**
787      * INTERNAL:
788      * Execute the post delete operation for the query
789      */

790     public void postDelete(DeleteObjectQuery query) {
791         // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
792
Vector mappings = getDescriptor().getMappings();
793         for (int index = 0; index < mappings.size(); index++) {
794             ((DatabaseMapping)mappings.get(index)).postDelete(query);
795         }
796     }
797
798     /**
799      * INTERNAL:
800      * Execute the post insert operation for the query
801      */

802     public void postInsert(WriteObjectQuery query) {
803         // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
804
Vector mappings = getDescriptor().getMappings();
805         for (int index = 0; index < mappings.size(); index++) {
806             ((DatabaseMapping)mappings.get(index)).postInsert(query);
807         }
808     }
809
810     /**
811      * INTERNAL:
812      * Execute the post update operation for the query
813      */

814     public void postUpdate(WriteObjectQuery query) {
815         // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
816
Vector mappings = getDescriptor().getMappings();
817         for (int index = 0; index < mappings.size(); index++) {
818             ((DatabaseMapping)mappings.get(index)).postUpdate(query);
819         }
820     }
821
822     /**
823      * INTERNAL:
824      * Execute the pre delete operation for the query
825      */

826     public void preDelete(DeleteObjectQuery query) {
827         // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
828
Vector mappings = getDescriptor().getMappings();
829         for (int index = 0; index < mappings.size(); index++) {
830             ((DatabaseMapping)mappings.get(index)).preDelete(query);
831         }
832     }
833
834     /**
835      * INTERNAL:
836      * Initialize the query manager.
837      * Any custom queries must be inherited from the parent before any initialization.
838      */

839     public void preInitialize(AbstractSession session) {
840         if (getDescriptor().isAggregateDescriptor()) {
841             return;
842         }
843
844         // Must inherit parent query customization if not redefined.
845
if (getDescriptor().isChildDescriptor()) {
846             DescriptorQueryManager parentQueryManager = getDescriptor().getInheritancePolicy().getParentDescriptor().getQueryManager();
847
848             if ((!hasInsertQuery()) && (parentQueryManager.hasInsertQuery())) {
849                 setInsertQuery((InsertObjectQuery)parentQueryManager.getInsertQuery().clone());
850             }
851             if ((!hasUpdateQuery()) && (parentQueryManager.hasUpdateQuery())) {
852                 setUpdateQuery((UpdateObjectQuery)parentQueryManager.getUpdateQuery().clone());
853             }
854             if ((!hasDeleteQuery()) && (parentQueryManager.hasDeleteQuery())) {
855                 setDeleteQuery((DeleteObjectQuery)parentQueryManager.getDeleteQuery().clone());
856             }
857             if ((!hasReadObjectQuery()) && (parentQueryManager.hasReadObjectQuery())) {
858                 setReadObjectQuery((ReadObjectQuery)parentQueryManager.getReadObjectQuery().clone());
859             }
860             if ((!hasReadAllQuery()) && (parentQueryManager.hasReadAllQuery())) {
861                 setReadAllQuery((ReadAllQuery)parentQueryManager.getReadAllQuery().clone());
862             }
863             if ((!getDoesExistQuery().isUserDefined()) && getDoesExistQuery().shouldCheckCacheForDoesExist()) {
864                 setDoesExistQuery(((DoesExistQuery)parentQueryManager.getDoesExistQuery().clone()));
865             }
866         }
867     }
868
869     /**
870      * INTERNAL:
871      * Execute the pre insert operation for the query.
872      */

873     public void preInsert(WriteObjectQuery query) {
874         // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
875
Vector mappings = getDescriptor().getMappings();
876         for (int index = 0; index < mappings.size(); index++) {
877             ((DatabaseMapping)mappings.get(index)).preInsert(query);
878         }
879     }
880
881     /**
882      * INTERNAL:
883      * Execute the pre update operation for the query
884      */

885     public void preUpdate(WriteObjectQuery query) {
886         // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
887
Vector mappings = getDescriptor().getMappings();
888         for (int index = 0; index < mappings.size(); index++) {
889             ((DatabaseMapping)mappings.get(index)).preUpdate(query);
890         }
891     }
892
893     /**
894      * PUBLIC:
895      * Remove all queries with the given query name from the set of pre-defined queries
896      *
897      * @see #removeQuery(String, Vector)
898      */

899     public void removeQuery(String JavaDoc queryName) {
900         queries.remove(queryName);
901     }
902
903     /**
904      * PUBLIC:
905      * Remove the specific query with the given queryName and argumentTypes.
906      *
907      * @see #removeQuery(String)
908      */

909     public void removeQuery(String JavaDoc queryName, Vector argumentTypes) {
910         Vector queries = (Vector)getQueries().get(queryName);
911         if (queries == null) {
912             return;
913         } else {
914             DatabaseQuery query = null;
915             for (Enumeration enumtr = queries.elements(); enumtr.hasMoreElements();) {
916                 query = (DatabaseQuery)enumtr.nextElement();
917                 if (Helper.areTypesAssignable(argumentTypes, query.getArgumentTypes())) {
918                     break;
919                 }
920             }
921             if (query != null) {
922                 queries.remove(query);
923             }
924         }
925     }
926
927     /**
928      * ADVANCED:
929      * Set the additional join expression. Used in conjuction with
930      * multiple tables and inheritance relationships.
931      * This can also be used if a sub-expression is always required to be
932      * appended to all queries. Such as tables that are shared based on a type field
933      * without inheritance.
934      */

935     public void setAdditionalJoinExpression(Expression additionalJoinExpression) {
936         this.additionalJoinExpression = additionalJoinExpression;
937     }
938
939     /**
940      * ADVANCED:
941      * Set the receiver's delete query.
942      * This should be an instance of a valid subclas of DeleteObjectQuery.
943      * If specified this is used by the descriptor to delete itself and its private parts from the database.
944      * This gives the user the ability to define exactly how to delete the data from the database,
945      * or access data external from the database or from some other framework.
946      */

947     public void setDeleteQuery(DeleteObjectQuery query) {
948         this.deleteQuery = query;
949         if (query == null) {
950             return;
951         }
952         this.deleteQuery.setIsUserDefined(true);
953         this.deleteQuery.setDescriptor(getDescriptor());
954
955     }
956
957     /**
958      * ADVANCED:
959      * Set the receiver's delete SQL string.
960      * This allows the user to override the SQL generated by TopLink, with their own SQL or procedure call.
961      * The arguments are translated from the fields of the source row,
962      * through replacing the field names marked by '#' with the values for those fields.
963      * <p>
964      * Example, "delete from EMPLOYEE where EMPLOYEE_ID = #EMPLOYEE_ID".
965      */

966     public void setDeleteSQLString(String JavaDoc sqlString) {
967         if (sqlString == null) {
968             return;
969         }
970
971         DeleteObjectQuery query = new DeleteObjectQuery();
972         query.setSQLString(sqlString);
973         setDeleteQuery(query);
974     }
975
976     /**
977      * ADVANCED:
978      * Set the receiver's delete call.
979      * This allows the user to override the delete operation.
980      */

981     public void setDeleteCall(Call call) {
982         if (call == null) {
983             return;
984         }
985         DeleteObjectQuery query = new DeleteObjectQuery();
986         query.setCall(call);
987         setDeleteQuery(query);
988     }
989
990     /**
991      * INTERNAL:
992      * Set the descriptor.
993      */

994     public void setDescriptor(ClassDescriptor descriptor) {
995         this.descriptor = descriptor;
996         //Gross alert: This is for the case when we are reading from XML, and
997
//we have to compensate for no descriptor available at read time. - JL
998
populateQueries();
999
1000    }
1001
1002    /**
1003     * ADVANCED:
1004     * Set the receiver's does exist query.
1005     * This should be an instance of a valid subclas of DoesExistQuery.
1006     * If specified this is used by the descriptor to query existence of an object in the database.
1007     * This gives the user the ability to define exactly how to query existence from the database,
1008     * or access data external from the database or from some other framework.
1009     */

1010    public void setDoesExistQuery(DoesExistQuery query) {
1011        this.doesExistQuery = query;
1012        if (query == null) {
1013            return;
1014        }
1015        this.doesExistQuery.setIsUserDefined(true);
1016        this.doesExistQuery.setDescriptor(getDescriptor());
1017    }
1018
1019    /**
1020     * ADVANCED:
1021     * Set the receiver's does exist SQL string.
1022     * This allows the user to override the SQL generated by TopLink, with there own SQL or procedure call.
1023     * The arguments are translated from the fields of the source row, through replacing the field names marked by '#'
1024     * with the values for those fields.
1025     * This must return null if the object does not exist, otherwise return a database row.
1026     * <p>
1027     * Example, "select EMPLOYEE_ID from EMPLOYEE where EMPLOYEE_ID = #EMPLOYEE_ID".
1028     */

1029    public void setDoesExistSQLString(String JavaDoc sqlString) {
1030        if (sqlString == null) {
1031            return;
1032        }
1033        getDoesExistQuery().setSQLString(sqlString);
1034        getDoesExistQuery().checkDatabaseForDoesExist();
1035    }
1036
1037    /**
1038     * ADVANCED:
1039     * Set the receiver's does exist call.
1040     * This allows the user to override the does exist operation.
1041     */

1042    public void setDoesExistCall(Call call) {
1043        if (call == null) {
1044            return;
1045        }
1046        getDoesExistQuery().setCall(call);
1047    }
1048
1049    /**
1050     * INTERNAL:
1051     * This method is explicitly used by the Builder only.
1052     */

1053    public void setExistenceCheck(String JavaDoc token) throws DescriptorException {
1054        if (token.equals("Check cache")) {
1055            checkCacheForDoesExist();
1056        } else if (token.equals("Check database")) {
1057            checkDatabaseForDoesExist();
1058        } else if (token.equals("Assume existence")) {
1059            assumeExistenceForDoesExist();
1060        } else if (token.equals("Assume non-existence")) {
1061            assumeNonExistenceForDoesExist();
1062        } else {
1063            throw DescriptorException.setExistenceCheckingNotUnderstood(token, getDescriptor());
1064        }
1065    }
1066
1067    /**
1068     * INTENAL:
1069     * Set if a cutsom join expression is used.
1070     */

1071    protected void setHasCustomMultipleTableJoinExpression(boolean hasCustomMultipleTableJoinExpression) {
1072        this.hasCustomMultipleTableJoinExpression = hasCustomMultipleTableJoinExpression;
1073    }
1074
1075    /**
1076     * ADVANCED:
1077     * Set the receiver's insert query.
1078     * This should be an instance of a valid subclass of InsertObjectQuery.
1079     * If specified this is used by the descriptor to insert itself into the database.
1080     * This gives the user the ability to define exactly how to insert the data into the database,
1081     * or access data external from the database or from some other framework.
1082     */

1083    public void setInsertQuery(InsertObjectQuery insertQuery) {
1084        this.insertQuery = insertQuery;
1085        if (insertQuery == null) {
1086            return;
1087        }
1088        this.insertQuery.setIsUserDefined(true);
1089        this.insertQuery.setDescriptor(getDescriptor());
1090    }
1091
1092    /**
1093     * ADVANCED:
1094     * Set the receiver's insert call.
1095     * This allows the user to override the insert operation.
1096     */

1097    public void setInsertCall(Call call) {
1098        if (call == null) {
1099            return;
1100        }
1101        InsertObjectQuery query = new InsertObjectQuery();
1102        query.setCall(call);
1103        setInsertQuery(query);
1104    }
1105
1106    /**
1107     * ADVANCED:
1108     * Set the receiver's insert SQL string.
1109     * This allows the user to override the SQL generated by TopLink, with their own SQL or procedure call.
1110     * The arguments are translated from the fields of the source row,
1111     * through replacing the field names marked by '#' with the values for those fields.
1112     * <p>
1113     * Example, "insert into EMPLOYEE (F_NAME, L_NAME) values (#F_NAME, #L_NAME)".
1114     */

1115    public void setInsertSQLString(String JavaDoc sqlString) {
1116        if (sqlString == null) {
1117            return;
1118        }
1119
1120        InsertObjectQuery query = new InsertObjectQuery();
1121        query.setSQLString(sqlString);
1122        setInsertQuery(query);
1123    }
1124
1125    /**
1126     * ADVANCED:
1127     * Return the receiver's insert call.
1128     * This allows the user to override the insert operation.
1129     */

1130    public Call getInsertCall() {
1131        if (getInsertQuery() == null) {
1132            return null;
1133        }
1134        return getInsertQuery().getDatasourceCall();
1135    }
1136
1137    /**
1138     * ADVANCED:
1139     * Return the receiver's update call.
1140     * This allows the user to override the update operation.
1141     */

1142    public Call getUpdateCall() {
1143        if (getUpdateQuery() == null) {
1144            return null;
1145        }
1146        return getUpdateQuery().getDatasourceCall();
1147    }
1148
1149    /**
1150     * ADVANCED:
1151     * Return the receiver's delete call.
1152     * This allows the user to override the delete operation.
1153     */

1154    public Call getDeleteCall() {
1155        if (getDeleteQuery() == null) {
1156            return null;
1157        }
1158        return getDeleteQuery().getDatasourceCall();
1159    }
1160
1161    /**
1162     * ADVANCED:
1163     * Return the receiver's read-object call.
1164     * This allows the user to override the read-object operation.
1165     */

1166    public Call getReadObjectCall() {
1167        if (getReadObjectQuery() == null) {
1168            return null;
1169        }
1170        return getReadObjectQuery().getDatasourceCall();
1171    }
1172
1173    /**
1174     * ADVANCED:
1175     * Return the receiver's read-all call.
1176     * This allows the user to override the read-all operation.
1177     */

1178    public Call getReadAllCall() {
1179        if (getReadAllQuery() == null) {
1180            return null;
1181        }
1182        return getReadAllQuery().getDatasourceCall();
1183    }
1184
1185    /**
1186     * ADVANCED:
1187     * Return the receiver's does-exist call.
1188     * This allows the user to override the does-exist operation.
1189     */

1190    public Call getDoesExistCall() {
1191        if (getDoesExistQuery() == null) {
1192            return null;
1193        }
1194        return getDoesExistQuery().getDatasourceCall();
1195    }
1196
1197    /**
1198     * INTERNAL:
1199     * Used in case descriptor has additional tables:
1200     * each additional table mapped to an expression joining it.
1201     */

1202    public Map getTablesJoinExpressions() {
1203        if(tablesJoinExpressions == null) {
1204            tablesJoinExpressions = new HashMap();
1205        }
1206        return tablesJoinExpressions;
1207    }
1208    
1209    /**
1210     * INTERNAL:
1211     * Used to set the multiple table join expression that was generated by TopLink as opposed
1212     * to a custom one supplied by the user.
1213     * @see #setMultipleTableJoinExpression(Expression)
1214     */

1215    public void setInternalMultipleTableJoinExpression(Expression multipleTableJoinExpression) {
1216        this.multipleTableJoinExpression = multipleTableJoinExpression;
1217    }
1218
1219    /**
1220     * ADVANCED:
1221     * This is normally generated for descriptors that have multiple tables.
1222     * However, if the additional table does not reference the primary table's primary key,
1223     * this expression may be set directly.
1224     */

1225    public void setMultipleTableJoinExpression(Expression multipleTableJoinExpression) {
1226        this.multipleTableJoinExpression = multipleTableJoinExpression;
1227        setHasCustomMultipleTableJoinExpression(true);
1228    }
1229
1230    /**
1231     * ADVANCED:
1232     * Set the receiver's read all query.
1233     * This should be an instance of a valid subclass of ReadAllQuery.
1234     * If specified this is used by the descriptor to read all instances of its class from the database.
1235     * This gives the user the ability to define exactly how to read all objects from the database,
1236     * or access data external from the database or from some other framework.
1237     * Note that this is only used on readAllObjects(Class), and not when an expression is provided.
1238     */

1239    public void setReadAllQuery(ReadAllQuery query) {
1240        this.readAllQuery = query;
1241        if (query == null) {
1242            return;
1243        }
1244
1245        this.readAllQuery.setIsUserDefined(true);
1246
1247        /* CR2260 - Steven Vo
1248         * Description:
1249         * NullPointerException accessing null descriptor
1250         * Fix:
1251         * Setting query's descriptor and reference class when descriptor is not null.
1252         * Otherwise, wait until the descriptor is set.See populateQueries() that is
1253         * called by setDescriptor()
1254         */

1255        if (this.getDescriptor() != null) {
1256            this.readAllQuery.setDescriptor(getDescriptor());
1257            this.readAllQuery.setReferenceClassName(getDescriptor().getJavaClassName());
1258            try {
1259                readAllQuery.setReferenceClass(getDescriptor().getJavaClass());
1260            } catch (ConversionException exception) {
1261            }
1262        }
1263    }
1264
1265    /**
1266     * ADVANCED:
1267     * Set the receiver's read SQL string.
1268     * This allows the user to override the SQL generated by TopLink, with their own SQL or procedure call.
1269     * The arguments are translated from the fields of the read arguments row,
1270     * through replacing the field names marked by '#' with the values for those fields.
1271     * Note that this is only used on readAllObjects(Class), and not when an expression is provided.
1272     * <p>
1273     * Example, "select * from EMPLOYEE"
1274     */

1275    public void setReadAllSQLString(String JavaDoc sqlString) {
1276        if (sqlString == null) {
1277            return;
1278        }
1279
1280        ReadAllQuery query = new ReadAllQuery();
1281        query.setSQLString(sqlString);
1282        setReadAllQuery(query);
1283    }
1284
1285    /**
1286     * ADVANCED:
1287     * Set the receiver's read all call.
1288     * This allows the user to override the read all operation.
1289     * Note that this is only used on readAllObjects(Class), and not when an expression is provided.
1290     */

1291    public void setReadAllCall(Call call) {
1292        if (call == null) {
1293            return;
1294        }
1295        ReadAllQuery query = new ReadAllQuery();
1296        query.setCall(call);
1297        setReadAllQuery(query);
1298    }
1299
1300    /**
1301     * ADVANCED:
1302     * Set the receiver's read query.
1303     * This should be an instance of a valid subclass of ReadObjectQuery>
1304     * If specified this is used by the descriptor to read itself from the database.
1305     * The read arguments must be the primary key of the object only.
1306     * This gives the user the ability to define exactly how to read the object from the database,
1307     * or access data external from the database or from some other framework.
1308     */

1309    public void setReadObjectQuery(ReadObjectQuery query) {
1310        this.readObjectQuery = query;
1311        if (query == null) {
1312            return;
1313        }
1314        this.readObjectQuery.setIsUserDefined(true);
1315
1316        /* CR2260 - Steven Vo
1317         * Description:
1318         * NullPointerException accessing null descriptor
1319         * Fix:
1320         * Setting query's descriptor and reference class when descriptor is not null.
1321         * Otherwise, wait until the descriptor is set.See populateQueries() that is
1322         * called by setDescriptor()
1323         */

1324        if (this.getDescriptor() != null) {
1325            this.readObjectQuery.setDescriptor(getDescriptor());
1326            this.readObjectQuery.setReferenceClassName(getDescriptor().getJavaClassName());
1327            try {
1328                readObjectQuery.setReferenceClass(getDescriptor().getJavaClass());
1329            } catch (ConversionException exception) {
1330            }
1331        }
1332    }
1333
1334    /**
1335     * ADVANCED:
1336     * Set the receiver's read SQL string.
1337     * This allows the user to override the SQL generated by TopLink, with their own SQL or procedure call.
1338     * The arguments are translated from the fields of the read arguments row,
1339     * through replacing the field names marked by '#' with the values for those fields.
1340     * This must accept only the primary key of the object as arguments.
1341     * <p>
1342     * Example, "select * from EMPLOYEE where EMPLOYEE_ID = #EMPLOYEE_ID"
1343     */

1344    public void setReadObjectSQLString(String JavaDoc sqlString) {
1345        if (sqlString == null) {
1346            return;
1347        }
1348
1349        ReadObjectQuery query = new ReadObjectQuery();
1350        query.setSQLString(sqlString);
1351        setReadObjectQuery(query);
1352    }
1353
1354    /**
1355     * ADVANCED:
1356     * Set the receiver's read object call.
1357     * This allows the user to override the read object operation.
1358     * This must accept only the primary key of the object as arguments.
1359     */

1360    public void setReadObjectCall(Call call) {
1361        if (call == null) {
1362            return;
1363        }
1364        ReadObjectQuery query = new ReadObjectQuery();
1365        query.setCall(call);
1366        setReadObjectQuery(query);
1367    }
1368
1369    /**
1370     * ADVANCED:
1371     * Set the receiver's update query.
1372     * This should be an instance of a valid subclass of UpdateObjectQuery.
1373     * If specified this is used by the descriptor to update itself in the database.
1374     * If the receiver uses optimisitic locking this must raise an error on optimisitic lock failure.
1375     * This gives the user the ability to define exactly how to update the data into the database,
1376     * or access data external from the database or from some other framework.
1377     */

1378    public void setUpdateQuery(UpdateObjectQuery updateQuery) {
1379        this.updateQuery = updateQuery;
1380        if (updateQuery == null) {
1381            return;
1382        }
1383        this.updateQuery.setIsUserDefined(true);
1384        this.updateQuery.setDescriptor(getDescriptor());
1385    }
1386
1387    /**
1388     * ADVANCED:
1389     * Set the receiver's update SQL string.
1390     * This allows the user to override the SQL generated by TopLink, with there own SQL or procedure call.
1391     * The arguments are translated from the fields of the source row,
1392     * through replacing the field names marked by '#' with the values for those fields.
1393     * This must check the optimistic lock field and raise an error on optimistic lock failure.
1394     * <p>
1395     * Example, "update EMPLOYEE set F_NAME to #F_NAME, L_NAME to #L_NAME where EMPLOYEE_ID = #EMPLOYEE_ID".
1396     */

1397    public void setUpdateSQLString(String JavaDoc sqlString) {
1398        if (sqlString == null) {
1399            return;
1400        }
1401
1402        UpdateObjectQuery query = new UpdateObjectQuery();
1403        query.setSQLString(sqlString);
1404        setUpdateQuery(query);
1405    }
1406
1407    /**
1408     * ADVANCED:
1409     * Set the receiver's update call.
1410     * This allows the user to override the update operation.
1411     */

1412    public void setUpdateCall(Call call) {
1413        if (call == null) {
1414            return;
1415        }
1416        UpdateObjectQuery query = new UpdateObjectQuery();
1417        query.setCall(call);
1418        setUpdateQuery(query);
1419    }
1420}
1421
Popular Tags