KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > queryframework > ObjectLevelReadQuery


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.queryframework;
23
24 import java.util.*;
25 import oracle.toplink.essentials.exceptions.*;
26 import oracle.toplink.essentials.expressions.*;
27 import oracle.toplink.essentials.internal.expressions.*;
28 import oracle.toplink.essentials.internal.helper.*;
29 import oracle.toplink.essentials.internal.queryframework.*;
30 import oracle.toplink.essentials.mappings.*;
31 import oracle.toplink.essentials.querykeys.*;
32 import oracle.toplink.essentials.internal.sessions.AbstractRecord;
33 import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl;
34 import oracle.toplink.essentials.internal.sessions.AbstractSession;
35 import oracle.toplink.essentials.descriptors.ClassDescriptor;
36
37
38 /**
39  * <p><b>Purpose</b>:
40  * Abstract class for all read queries using objects.
41  *
42  * <p><b>Description</b>:
43  * Contains common behavior for all read queries using objects.
44  *
45  * @author Yvon Lavoie
46  * @since TOPLink/Java 1.0
47  */

48 public abstract class ObjectLevelReadQuery extends ObjectBuildingQuery {
49
50     /** Provide a default builder so that it's easier to be consistent */
51     protected ExpressionBuilder defaultBuilder;
52
53     /** Allows for the resulting objects to be refresh with the data from the database. */
54     protected boolean shouldRefreshIdentityMapResult;
55
56     /** Allow for the cache usage to be specified to enable in-memory querying. */
57     protected int cacheUsage;
58
59     // Note: UseDescriptorSetting will result in CheckCacheByPrimaryKey for most cases
60
// it simply allows the Descriptor's disable cache hits to be used
61
public static final int UseDescriptorSetting = -1;
62     public static final int DoNotCheckCache = 0;
63     public static final int CheckCacheByExactPrimaryKey = 1;
64     public static final int CheckCacheByPrimaryKey = 2;
65     public static final int CheckCacheThenDatabase = 3;
66     public static final int CheckCacheOnly = 4;
67     public static final int ConformResultsInUnitOfWork = 5;
68
69     /** INTERNAL: for bug 2612601 allow ability not to register results in UOW. */
70     protected boolean shouldRegisterResultsInUnitOfWork = true;
71
72     /** Allow for additional fields to be selected, used for m-m batch reading. */
73     protected Vector additionalFields;
74
75     /** Allow for a complex result to be return including the rows and objects, used for m-m batch reading. */
76     protected boolean shouldIncludeData;
77
78     /** CMP only. Allow users to configure whether finder should be executed in a uow or not. */
79     protected boolean shouldProcessResultsInUnitOfWork = true;
80
81     /** Indicates if distinct should be used or not. */
82     protected short distinctState;
83     public static final short UNCOMPUTED_DISTINCT = 0;
84     public static final short USE_DISTINCT = 1;
85     public static final short DONT_USE_DISTINCT = 2;
86
87     /**
88      * CR 3677
89      * Used to determine behaviour of indirection in InMemoryQuerying
90      * This should have been just a constant similar to distinct locking, etc. instead of an object that just has the state and no behavoir,
91      * the object instantiation adds un-needed overhead, but too late now.
92      */

93     protected InMemoryQueryIndirectionPolicy inMemoryQueryIndirectionPolicy;
94
95     /**
96      * Used to set the read time on objects that use this query.
97      * Should be set to the time the query returned from the database.
98      */

99     protected long executionTime = 0;
100
101     /**
102      * INTERNAL: This is the key for accessing unregistered and locked result in the query's properties.
103      * The uow and QueryBaseValueHolder use this property to record amd to retreive the result respectively.
104      */

105     public static final String JavaDoc LOCK_RESULT_PROPERTY = "LOCK_RESULT";
106
107     /** Allow for a query level fetch group to be set. */
108     protected FetchGroup fetchGroup;
109
110     /** The pre-defined fetch group name. */
111     protected String JavaDoc fetchGroupName;
112
113     /** Flag to turn on/off the use of the default fetch group. */
114     protected boolean shouldUseDefaultFetchGroup = true;
115
116     /** PERF: Store if the query originally used the default lock mode. */
117     protected boolean wasDefaultLockMode = false;
118     
119     /** Stores the non fetchjoin attributes, these are joins that will be
120      * represented in the where clause but not in the select */

121     protected Vector nonFetchJoinAttributeExpressions;
122
123     /** Stores the helper object for dealing with joined attributes */
124     protected JoinedAttributeManager joinedAttributeManager;
125     
126     /**
127      * INTERNAL:
128      * Initialize the state of the query
129      */

130     public ObjectLevelReadQuery() {
131         this.shouldRefreshIdentityMapResult = false;
132         this.distinctState = UNCOMPUTED_DISTINCT;
133         this.joinedAttributeManager = new JoinedAttributeManager(getDescriptor(), getExpressionBuilder(), this);
134         this.additionalFields = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(1);
135         this.cacheUsage = UseDescriptorSetting;
136         this.shouldIncludeData = false;
137         this.inMemoryQueryIndirectionPolicy = new InMemoryQueryIndirectionPolicy();
138     }
139
140     /**
141      * INTERNAL:
142      * Return if this query originally used the default lock mode.
143      */

144     protected boolean wasDefaultLockMode() {
145         return wasDefaultLockMode;
146     }
147     
148     /**
149      * INTERNAL:
150      * Set if this query originally used the default lock mode.
151      */

152     protected void setWasDefaultLockMode(boolean wasDefaultLockMode) {
153         this.wasDefaultLockMode = wasDefaultLockMode;
154     }
155     
156     /**
157      * INTERNAL:
158      * Clone the query
159      */

160     public Object JavaDoc clone() {
161         ObjectLevelReadQuery cloneQuery = (ObjectLevelReadQuery)super.clone();
162
163         //CR#... must also clone the joined expressions as always joined attribute will be added
164
// don't use setters as this will trigger unprepare.
165
cloneQuery.joinedAttributeManager = (JoinedAttributeManager)cloneQuery.getJoinedAttributeManager().clone();
166         if (hasNonFetchJoinedAttributeExpressions()){
167             cloneQuery.setNonFetchJoinAttributeExpressions((Vector)this.nonFetchJoinAttributeExpressions.clone());
168         }
169         cloneQuery.joinedAttributeManager.setBaseQuery(cloneQuery);
170         return cloneQuery;
171     }
172
173     /**
174      * INTERNAL:
175      * Clone the query, including its selection criteria.
176      * <p>
177      * Normally selection criteria are not cloned here as they are cloned
178      * later on during prepare.
179      */

180     public Object JavaDoc deepClone() {
181         ObjectLevelReadQuery clone = (ObjectLevelReadQuery)clone();
182         if (getSelectionCriteria() != null) {
183             clone.setSelectionCriteria((Expression)getSelectionCriteria().clone());
184         } else if (defaultBuilder != null) {
185             clone.defaultBuilder = (ExpressionBuilder)defaultBuilder.clone();
186         }
187         return clone;
188     }
189
190     /**
191      * PUBLIC:
192      * Set the query to lock, this will also turn refreshCache on.
193      */

194     public void acquireLocks() {
195         setLockMode(LOCK);
196         //Bug2804042 Must un-prepare if prepared as the SQL may change.
197
setIsPrepared(false);
198     }
199
200     /**
201      * PUBLIC:
202      * Set the query to lock without waiting (blocking), this will also turn refreshCache on.
203      */

204     public void acquireLocksWithoutWaiting() {
205         setLockMode(LOCK_NOWAIT);
206         //Bug2804042 Must un-prepare if prepared as the SQL may change.
207
setIsPrepared(false);
208     }
209
210     /**
211      * INTERNAL:
212      * Additional fields can be added to a query. This is used in m-m bacth reading to bring back the key from the join table.
213      */

214     public void addAdditionalField(DatabaseField field) {
215         getAdditionalFields().addElement(field);
216         //Bug2804042 Must un-prepare if prepared as the SQL may change.
217
setIsPrepared(false);
218     }
219
220     /**
221      * INTERNAL:
222      * Additional fields can be added to a query. This is used in m-m bacth reading to bring back the key from the join table.
223      */

224     public void addAdditionalField(Expression fieldExpression) {
225         getAdditionalFields().addElement(fieldExpression);
226         //Bug2804042 Must un-prepare if prepared as the SQL may change.
227
setIsPrepared(false);
228     }
229
230     /**
231      * PUBLIC:
232      * Specify the one-to-one mapped attribute to be optimized in this query.
233      * The query will join the object(s) being read with the one-to-one attribute,
234      * this allows all of the data required for the object(s) to be read in a single query instead of (n) queries.
235      * This should be used when the application knows that it requires the part for all of the objects being read.
236      * This can be used only for one-to-one mappings where the target is not the same class as the source,
237      * either directly or through inheritance. Also two joins cannot be done to the same class.
238      *
239      * <p>Note: This cannot be used for objects where it is possible not to have a part,
240      * as these objects will be ommited from the result set,
241      * unless an outer join is used through passing and expression using "getAllowingNull".
242      *
243      * <p>Example: query.addJoinedAttribute("address")
244      *
245      * @see #addJoinedAttribute(Expression)
246      */

247     public void addJoinedAttribute(String JavaDoc attributeName) {
248         addJoinedAttribute(getExpressionBuilder().get(attributeName));
249     }
250
251     /**
252      * PUBLIC:
253      * Specify the to-one or to-many mapped attribute to be optimized in this query.
254      * The query will join the object(s) being read with the specified attribute,
255      * this allows all of the data required for the object(s) to be read in a single query instead of (n) queries.
256      * This should be used when the application knows that it requires the part for all of the objects being read.
257      *
258      * <p>Note: This cannot be used for objects where it is possible not to have a part,
259      * as these objects will be ommited from the result set,
260      * unless an outer join is used through passing and expression using "getAllowingNull".
261      *
262      * <p>Example:
263      * The following will fetch along with Employee(s) "Jones" all projects they participate in
264      * along with teamLeaders and their addresses, teamMembers and their phones.
265      *
266      * query.setSelectionCriteria(query.getExpressionBuilder().get("lastName").equal("Jones"));
267      * Expression projects = query.getExpressionBuilder().anyOf("projects");
268      * query.addJoinedAttribute(projects);
269      * Expression teamLeader = projects.get("teamLeader");
270      * query.addJoinedAttribute(teamLeader);
271      * Expression teamLeaderAddress = teamLeader.getAllowingNull("address");
272      * query.addJoinedAttribute(teamLeaderAddress);
273      * Expression teamMembers = projects.anyOf("teamMembers");
274      * query.addJoinedAttribute(teamMembers);
275      * Expression teamMembersPhones = teamMembers.anyOfAllowingNone("phoneNumbers");
276      * query.addJoinedAttribute(teamMembersPhones);
277      *
278      * Note that:
279      * the order is essential: an expression should be added before any expression derived from it;
280      * the object is built once - it won't be rebuilt if it to be read again as a joined attribute:
281      * in the example the query won't get phones for "Jones" -
282      * even though they are among teamMembers (for whom phones are read).
283      *
284      */

285     public void addJoinedAttribute(Expression attributeExpression) {
286         getJoinedAttributeManager().addJoinedAttributeExpression(attributeExpression);
287         //Bug2804042 Must un-prepare if prepared as the SQL may change.
288
// Joined attributes are now calculated in prePrepare.
289
setIsPrePrepared(false);
290     }
291
292     /**
293      * PUBLIC:
294      * Specify the one-to-one mapped attribute to be optimized in this query.
295      * The query will join the object(s) being read with the one-to-one
296      * attribute. The difference between this and a joined attribute is that
297      * it allows data to be retrieved based on a join, but will not populate
298      * the joined attribute. It also allows all of the data required for the
299      * object(s) to be read in a single query instead of (n) queries. This
300      * should be used when the application knows that it requires the part for
301      * all of the objects being read. This can be used only for one-to-one
302      * mappings where the target is not the same class as the source, either
303      * directly or through inheritance. Also two joins cannot be done to the
304      * same class.
305      *
306      * <p>Note: This cannot be used for objects where it is possible not to have
307      * a part, as these objects will be ommited from the result set, unless an
308      * outer join is used through passing and expression using "getAllowingNull".
309      *
310      * <p>Example: query.addNonFetchJoinedAttribute("address")
311      *
312      * @see #addNonFetchJoinedAttribute(Expression)
313      */

314     public void addNonFetchJoinedAttribute(String JavaDoc attributeName) {
315         addNonFetchJoinedAttribute(getExpressionBuilder().get(attributeName));
316     }
317
318     /**
319      * PUBLIC:
320      * Specify the one-to-one mapped attribute to be optimized in this query.
321      * The query will join the object(s) being read with the one-to-one
322      * attribute. The difference between this and a joined attribute is that
323      * it allows data to be retrieved based on a join, but will not populate
324      * the joined attribute. It also allows all of the data required for the
325      * object(s) to be read in a single query instead of (n) queries. This
326      * should be used when the application knows that it requires the part for
327      * all of the objects being read. This can be used only for one-to-one
328      * mappings where the target is not the same class as the source, either
329      * directly or through inheritance. Also two joins cannot be done to the
330      * same class.
331      *
332      * <p>Note: This cannot be used for objects where it is possible not to have
333      * a part, as these objects will be ommited from the result set, unless an
334      * outer join is used through passing and expression using "getAllowingNull".
335      *
336      * <p>Example: query.addNonFetchJoinedAttribute(query.getExpressionBuilder().get("teamLeader").get("address"))
337      *
338      * @see #addNonFetchJoinedAttribute(Expression)
339      */

340     public void addNonFetchJoinedAttribute(Expression attributeExpression) {
341         getNonFetchJoinAttributeExpressions().add(attributeExpression);
342         
343         // Bug 2804042 Must un-prepare if prepared as the SQL may change.
344
// Joined attributes are now calculated in prePrepare.
345
setIsPrePrepared(false);
346     }
347
348     /**
349      * INTERNAL:
350      * Iterate through a list of joined expressions and add the fields they represent to a list
351      * of fields.
352      */

353     protected void addSelectionFieldsForJoinedExpressions(List fields, List joinedExpressions) {
354         for (int index = 0; index < joinedExpressions.size(); index++) {
355             ObjectExpression objectExpression = (ObjectExpression)joinedExpressions.get(index);
356
357             // Expression may not have been initialized.
358
objectExpression.getBuilder().setSession(getSession());
359             objectExpression.getBuilder().setQueryClass(getReferenceClass());
360             ClassDescriptor descriptor = objectExpression.getMapping().getReferenceDescriptor();
361             fields.addAll(descriptor.getFields());
362         }
363     }
364
365     /**
366      * INTERNAL:
367      * Called by CursoredStream to construct objects from rows.
368      * Subclasses which build other results objects (ReportQuery, & PartialObjects) may override
369      */

370     public Object JavaDoc buildObject(AbstractRecord row) {
371         return getDescriptor().getObjectBuilder().buildObject(this, row, this.getJoinedAttributeManager());
372     }
373
374     /**
375      * PUBLIC:
376      * The cache will checked completely, if the object is not found null will be returned or an error if the query is too complex.
377      * Queries can be configured to use the cache at several levels.
378      * Other caching option are available.
379      * @see #setCacheUsage(int)
380      */

381     public void checkCacheOnly() {
382         setCacheUsage(CheckCacheOnly);
383     }
384
385     /**
386      * INTERNAL:
387      * Ensure that the descriptor has been set.
388      */

389     public void checkDescriptor(AbstractSession session) throws QueryException {
390         if (getReferenceClass() == null) {
391             throw QueryException.referenceClassMissing(this);
392         }
393
394         if (getDescriptor() == null) {
395             ClassDescriptor referenceDescriptor = session.getDescriptor(getReferenceClass());
396             if (referenceDescriptor == null) {
397                 throw QueryException.descriptorIsMissing(getReferenceClass(), this);
398             }
399             setDescriptor(referenceDescriptor);
400         }
401     }
402
403     /**
404      * INTERNAL:
405      * Contains the body of the check early return call, implemented by subclasses.
406      */

407     protected abstract Object JavaDoc checkEarlyReturnImpl(AbstractSession session, AbstractRecord translationRow);
408
409     /**
410      * INTERNAL:
411      * Check to see if this query already knows the return vale without preforming any further work.
412      */

413     public Object JavaDoc checkEarlyReturn(AbstractSession session, AbstractRecord translationRow) {
414         // For bug 3136413/2610803 building the selection criteria from an EJBQL string or
415
// an example object is done just in time.
416
// Also calls checkDescriptor here.
417
//buildSelectionCriteria(session);
418
checkPrePrepare(session);
419
420         if (!session.isUnitOfWork()) {
421             return checkEarlyReturnImpl(session, translationRow);
422         }
423         UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)session;
424
425         // The cache check must happen on the UnitOfWork in these cases either
426
// to access transient state or for pessimistic locking, as only the
427
// UOW knows which objects it has locked.
428
if (shouldCheckCacheOnly() || shouldConformResultsInUnitOfWork() || getDescriptor().shouldAlwaysConformResultsInUnitOfWork() || (getLockMode() != ObjectBuildingQuery.NO_LOCK)) {
429             Object JavaDoc result = checkEarlyReturnImpl(unitOfWork, translationRow);
430             if (result != null) {
431                 return result;
432             }
433         }
434
435         // don't bother trying to get a cache hit on the parent session
436
// as if not in UnitOfWork it is not yet pessimistically locked
437
// on the database for sure.
438
// Note for ReadObjectQueries we totally ignore shouldCheckCacheOnly.
439
if (isReadObjectQuery() && isLockQuery()) {
440             return null;
441         }
442
443         // follow the execution path in looking for the object.
444
AbstractSession parentSession = unitOfWork.getParentIdentityMapSession(this);
445
446         // assert parentSession != unitOfWork;
447
Object JavaDoc result = checkEarlyReturn(parentSession, translationRow);
448
449         if (result != null) {
450             // Optimization: If find deleted object by exact primary key
451
// treat this as cache hit but return null. Bug 2782991.
452
if (result == InvalidObject.instance) {
453                 return result;
454             }
455             return registerResultInUnitOfWork(result, unitOfWork, translationRow, false);
456         } else {
457             return null;
458         }
459     }
460
461     /**
462      * INTERNAL:
463      * Check to see if this query needs to be prepare and prepare it.
464      * The prepare is done on the original query to ensure that the work is not repeated.
465      */

466     public void checkPrepare(AbstractSession session, AbstractRecord translationRow) {
467         // CR#3823735 For custom queries the prePrepare may not have been called yet.
468
checkPrePrepare(session);
469         super.checkPrepare(session, translationRow);
470     }
471
472     /**
473      * INTERNAL:
474      * ObjectLevelReadQueries now have an explicit pre-prepare stage, which
475      * is for checking for pessimistic locking, and computing any joined
476      * attributes declared on the descriptor.
477      */

478     protected void checkPrePrepare(AbstractSession session) {
479         checkDescriptor(session);
480         // This query is first prepared for global common state, this must be synced.
481
if (!isPrePrepared()) {// Avoid the monitor is already prePrepare, must check again for concurrency.
482
synchronized (this) {
483                 if (!isPrePrepared()) {
484                     AbstractSession alreadySetSession = getSession();
485                     setSession(session);// Session is required for some init stuff.
486
prePrepare();
487                     setSession(alreadySetSession);
488                     setIsPrePrepared(true);// MUST not set prepare until done as other thread may hit before finishing the prePrepare.
489
}
490             }
491         }
492     }
493
494     /**
495      * INTERNAL:
496      * The reference class has been changed, need to reset the
497      * descriptor. Null out the current descriptor and call
498      * checkDescriptor
499      * Added Feb 27, 2001 JED for EJBQL feature
500      */

501     public void changeDescriptor(AbstractSession theSession) {
502         setDescriptor(null);
503         checkDescriptor(theSession);
504     }
505
506     /**
507      * INTERNAL:
508      * Conforms and registers an individual result. This instance could be one
509      * of the elements returned from a read all query, the result of a Read Object
510      * query, or an element read from a cursor.
511      * <p>
512      * A result needs to be registered before it can be conformed, so
513      * registerIndividualResult is called here.
514      * <p>
515      * Conforming on a result from the database is lenient. Since the object
516      * matched the query on the database we assume it matches here unless we can
517      * determine for sure that it was changed in this UnitOfWork not to conform.
518      * @param result may be an original, or a raw database row
519      * @param arguments the parameters this query was executed with
520      * @param selectionCriteriaClone the expression to conform to. If was a
521      * selection object or key, null (which all conform to) is used
522      * @param alreadyReturned a hashtable of objects already found by scanning
523      * the UnitOfWork cache for conforming instances. Prevents duplicates.
524      * @param buildDirectlyFromRows whether result is an original or a raw database
525      * row
526      * @return a clone, or null if result does not conform.
527      */

528     protected Object JavaDoc conformIndividualResult(Object JavaDoc result, UnitOfWorkImpl unitOfWork, AbstractRecord arguments, Expression selectionCriteriaClone, IdentityHashtable alreadyReturned, boolean buildDirectlyFromRows) {
529         // First register the object. Since object is presently unwrapped the
530
// exact objects stored in the cache will be returned.
531
// The object is known to exist.
532
Object JavaDoc clone = registerIndividualResult(result, unitOfWork, buildDirectlyFromRows, null);
533
534         if (getDescriptor().hasWrapperPolicy() && getDescriptor().getWrapperPolicy().isWrapped(clone)) {
535             // The only time the clone could be wrapped is if we are not registering
536
// results in the unitOfWork and we are ready to return a final
537
// (unregistered) result now. Any further processing may accidently
538
// cause it to get registered.
539
return clone;
540         }
541         //bug 4459976 in order to maintain backward compatibility on ordering
542
// lets use the result as a guild for the final result not the hashtable
543
// of found objects.
544
if (unitOfWork.isObjectDeleted(clone) ) {
545             return null;
546         }
547         if (!isExpressionQuery() || (selectionCriteriaClone == null)) {
548             if (alreadyReturned != null) {
549                 alreadyReturned.remove(clone);
550             }
551             return clone;
552         }
553         try {
554             // pass in the policy to assume that the object conforms if indirection is not triggered. This
555
// is valid because the query returned the object and we should trust the query that the object
556
// matches the selection criteria, and because the indirection is not triggered then the customer
557
//has not changed the value.
558
// bug 2637555
559
// unless for bug 3568141 use the painstaking shouldTriggerIndirection if set
560
InMemoryQueryIndirectionPolicy policy = getInMemoryQueryIndirectionPolicy();
561             if (!policy.shouldTriggerIndirection()) {
562                 policy = new InMemoryQueryIndirectionPolicy(InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_CONFORMED);
563             }
564             if (selectionCriteriaClone.doesConform(clone, unitOfWork, arguments, policy)) {
565                  if (alreadyReturned != null) {
566                     alreadyReturned.remove(clone);
567                 }
568                return clone;
569             }
570         } catch (QueryException exception) {
571             // bug 3570561: mask all-pervasive valueholder exceptions while conforming
572
if ((unitOfWork.getShouldThrowConformExceptions() == UnitOfWorkImpl.THROW_ALL_CONFORM_EXCEPTIONS) && (exception.getErrorCode() != QueryException.MUST_INSTANTIATE_VALUEHOLDERS)) {
573                 throw exception;
574             }
575             if (alreadyReturned != null) {
576                 alreadyReturned.remove(clone);
577             }
578             return clone;
579         }
580         return null;
581     }
582
583     /**
584      * PUBLIC:
585      * The cache will checked completely, if the object is not found the database will be queried,
586      * and the database result will be verified with what is in the cache and/or unit of work including new objects.
587      * This can lead to poor performance so it is recomended that only the database be queried in most cases.
588      * Queries can be configured to use the cache at several levels.
589      * Other caching option are available.
590      * @see #setCacheUsage(int)
591      */

592     public void conformResultsInUnitOfWork() {
593         setCacheUsage(ConformResultsInUnitOfWork);
594     }
595
596     /**
597      * PUBLIC:
598      * Set the query not to lock.
599      */

600     public void dontAcquireLocks() {
601         setLockMode(NO_LOCK);
602         //Bug2804042 Must un-prepare if prepared as the SQL may change.
603
setIsPrepared(false);
604     }
605
606     /**
607      * PUBLIC:
608      * This can be used to explicitly disable the cache hit.
609      * The cache hit may not be desired in some cases, such as
610      * stored procedures that accept the primary key but do not query on it.
611      */

612     public void dontCheckCache() {
613         setCacheUsage(DoNotCheckCache);
614     }
615
616     /**
617      * PUBLIC:
618      * When unset means perform read normally and dont do refresh.
619      */

620     public void dontRefreshIdentityMapResult() {
621         setShouldRefreshIdentityMapResult(false);
622     }
623
624     /**
625      * ADVANCED:
626      * If a distinct has been set the DISTINCT clause will be printed.
627      * This is used internally by TopLink for batch reading but may also be
628      * used directly for advanced queries or report queries.
629      */

630     public void dontUseDistinct() {
631         setDistinctState(DONT_USE_DISTINCT);
632         //Bug2804042 Must un-prepare if prepared as the SQL may change.
633
setIsPrepared(false);
634     }
635
636     /**
637      * INTERNAL:
638      * There is a very special case where a query may be a bean-level
639      * pessimistic locking query.
640      * <p>
641      * If that is so, only queries executed inside of a UnitOfWork should
642      * have a locking clause. In the extremely rare case that we execute
643      * a locking query outside of a UnitOfWork, must disable locking so that
644      * we do not get a fetch out of sequence error.
645      */

646     public DatabaseQuery prepareOutsideUnitOfWork(AbstractSession session) {
647         // Implementation is complicated because: if locking refresh will be
648
// auto set to true preventing cache hit.
649
// Must prepare this query from scratch if outside uow but locking
650
// Must not reprepare this query as a NO_LOCK, but create a clone first
651
// Must not cloneAndUnPrepare unless really have to
652
if (isLockQuery(session) && getLockingClause().isForUpdateOfClause()) {
653             ObjectLevelReadQuery clone = (ObjectLevelReadQuery)clone();
654             clone.dontAcquireLocks();
655             clone.setIsPrepared(false);
656             clone.checkPrePrepare(session);
657             return clone;
658         }
659         return this;
660     }
661
662     /**
663      * INTERNAL:
664      * Execute the query. If there are objects in the cache return the results
665      * of the cache lookup.
666      *
667      * @param session - the session in which the receiver will be executed.
668      * @exception DatabaseException - an error has occurred on the database.
669      * @exception OptimisticLockException - an error has occurred using the optimistic lock feature.
670      * @return An object, the result of executing the query.
671      */

672     public Object JavaDoc execute(AbstractSession session, AbstractRecord translationRow) throws DatabaseException, OptimisticLockException {
673         //Bug#2839852 Refreshing is not possible if the query uses checkCacheOnly.
674
if (shouldRefreshIdentityMapResult() && shouldCheckCacheOnly()) {
675             throw QueryException.refreshNotPossibleWithCheckCacheOnly(this);
676         }
677         return super.execute(session, translationRow);
678     }
679
680     /*
681      * Executes the prepared query on the datastore.
682      */

683     public Object JavaDoc executeDatabaseQuery() throws DatabaseException {
684         if (getSession().isUnitOfWork()) {
685             UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)getSession();
686
687             // Note if a nested unit of work this will recursively start a
688
// transaction early on the parent also.
689
if (isLockQuery()) {
690                 if ((!unitOfWork.getCommitManager().isActive()) && (!unitOfWork.wasTransactionBegunPrematurely())) {
691                     unitOfWork.beginTransaction();
692                     unitOfWork.setWasTransactionBegunPrematurely(true);
693                 }
694             }
695             if (unitOfWork.isNestedUnitOfWork()) {
696                 UnitOfWorkImpl nestedUnitOfWork = (UnitOfWorkImpl)getSession();
697                 setSession(nestedUnitOfWork.getParent());
698                 Object JavaDoc result = executeDatabaseQuery();
699                 setSession(nestedUnitOfWork);
700                 return registerResultInUnitOfWork(result, nestedUnitOfWork, getTranslationRow(), false);
701             }
702         }
703         session.validateQuery(this);// this will update the query with any settings
704

705         if (getQueryId() == 0) {
706             setQueryId(getSession().getNextQueryId());
707         }
708
709         return executeObjectLevelReadQuery();
710     }
711
712     /*
713      * Executes the prepared query on the datastore.
714      */

715     protected abstract Object JavaDoc executeObjectLevelReadQuery() throws DatabaseException;
716
717     /**
718      * INTERNAL:
719      * At this point only the code has been copied over from UnitOfWork
720      * internalExecuteQuery. No work has been done.
721      * @param unitOfWork
722      * @param translationRow
723      * @return
724      * @throws oracle.toplink.essentials.exceptions.DatabaseException
725      * @throws oracle.toplink.essentials.exceptions.OptimisticLockException
726      */

727     public Object JavaDoc executeInUnitOfWork(UnitOfWorkImpl unitOfWork, AbstractRecord translationRow) throws DatabaseException, OptimisticLockException {
728         if (!shouldMaintainCache()) {
729             return unitOfWork.getParent().executeQuery(this, translationRow);
730         }
731         Object JavaDoc result = execute(unitOfWork, translationRow);
732
733         // Optimization: If find deleted object on uow by exact primary key
734
// treat this as cache hit but return null. Bug 2782991.
735
if (result == InvalidObject.instance) {
736             return null;
737         }
738         return result;
739     }
740
741     /**
742      * INTERNAL:
743      * Additional fields can be added to a query. This is used in m-m bacth reading to bring back the key from the join table.
744      */

745     public Vector getAdditionalFields() {
746         return additionalFields;
747     }
748
749     /**
750      * PUBLIC:
751      * Return the cache usage.
752      * By default only primary key read object queries will first check the cache before accessing the database.
753      * Any query can be configure to query against the cache completely, by key or ignore the cache check.
754      * <p>Valid values are:
755      * <ul>
756      * <li> DoNotCheckCache
757      * <li> CheckCacheByExactPrimaryKey
758      * <li> CheckCacheByPrimaryKey
759      * <li> CheckCacheThenDatabase
760      * <li> CheckCacheOnly
761      * <li> ConformResultsInUnitOfWork
762      * <li> UseDescriptorSetting
763      * Note: UseDescriptorSetting functions like CheckCacheByPrimaryKey, except checks the appropriate descriptor's
764      * shouldDisableCacheHits setting when querying on the cache.
765      * </lu>
766      */

767     public int getCacheUsage() {
768         return cacheUsage;
769     }
770
771     /**
772      * ADVANCED:
773      * If a distinct has been set the DISTINCT clause will be printed.
774      * This is used internally by TopLink for batch reading but may also be
775      * used directly for advanced queries or report queries.
776      */

777     public short getDistinctState() {
778         return distinctState;
779     }
780
781     /**
782      * REQUIRED:
783      * Get the expression builder which should be used for this query.
784      * This expression builder should be used to build all expressions used by this query.
785      */

786     public ExpressionBuilder getExpressionBuilder() {
787         if (defaultBuilder == null) {
788             initializeDefaultBuilder();
789         }
790
791         return defaultBuilder;
792     }
793
794     /**
795      * INTERNAL
796      * Sets the default expression builder for this query.
797      */

798     public void setExpressionBuilder(ExpressionBuilder builder) {
799         this.defaultBuilder = builder;
800     }
801
802     /**
803      * PUBLIC:
804      * Returns the InMemoryQueryIndirectionPolicy for this query
805      */

806     public InMemoryQueryIndirectionPolicy getInMemoryQueryIndirectionPolicy() {
807         return this.inMemoryQueryIndirectionPolicy;
808     }
809
810     /**
811      * INTERNAL:
812      * Set the list of expressions that represent elements that are joined because of their
813      * mapping for this query.
814      */

815     public JoinedAttributeManager getJoinedAttributeManager() {
816         return this.joinedAttributeManager;
817     }
818
819     /**
820      * INTERNAL:
821      * Return the attributes that must be joined, but not fetched, that is,
822      * do not trigger the value holder.
823      */

824     public Vector getNonFetchJoinAttributeExpressions() {
825         if (this.nonFetchJoinAttributeExpressions == null){
826             this.nonFetchJoinAttributeExpressions = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance();
827         }
828         return nonFetchJoinAttributeExpressions;
829     }
830
831     /**
832      * INTERNAL:
833      * Lookup the mapping for this item by traversing its expression recursively.
834      * If an aggregate of foreign mapping is found it is traversed.
835      */

836     public DatabaseMapping getLeafMappingFor(Expression expression, ClassDescriptor rootDescriptor) throws QueryException {
837         // Check for database field expressions or place holder
838
if ((expression == null) || (expression.isFieldExpression())) {
839             return null;
840         }
841
842         if (!(expression.isQueryKeyExpression())) {
843             return null;
844         }
845
846         QueryKeyExpression qkExpression = (QueryKeyExpression)expression;
847         Expression baseExpression = qkExpression.getBaseExpression();
848
849         ClassDescriptor descriptor = getLeafDescriptorFor(baseExpression, rootDescriptor);
850         return descriptor.getMappingForAttributeName(qkExpression.getName());
851     }
852
853     /**
854      * INTERNAL:
855      * Lookup the descriptor for this item by traversing its expression recursively.
856      * @param expression
857      * @param rootDescriptor
858      * @return
859      * @throws oracle.toplink.essentials.exceptions.QueryException
860      */

861     public ClassDescriptor getLeafDescriptorFor(Expression expression, ClassDescriptor rootDescriptor) throws QueryException {
862         // The base case
863
if (expression.isExpressionBuilder()) {
864             // The following special case is where there is a parallel builder
865
// which has a different reference class as the primary builder.
866
Class JavaDoc queryClass = ((ExpressionBuilder)expression).getQueryClass();
867             if ((queryClass != null) && (queryClass != getReferenceClass())) {
868                 return getSession().getDescriptor(queryClass);
869             }
870             return rootDescriptor;
871         }
872         Expression baseExpression = ((QueryKeyExpression)expression).getBaseExpression();
873         ClassDescriptor baseDescriptor = getLeafDescriptorFor(baseExpression, rootDescriptor);
874         ClassDescriptor descriptor = null;
875         String JavaDoc attributeName = expression.getName();
876
877         DatabaseMapping mapping = baseDescriptor.getMappingForAttributeName(attributeName);
878
879         if (mapping == null) {
880             QueryKey queryKey = baseDescriptor.getQueryKeyNamed(attributeName);
881             if (queryKey != null) {
882                 if (queryKey.isForeignReferenceQueryKey()) {
883                     descriptor = getSession().getDescriptor(((ForeignReferenceQueryKey)queryKey).getReferenceClass());
884                 } else// if (queryKey.isDirectQueryKey())
885
{
886                     descriptor = queryKey.getDescriptor();
887                 }
888             }
889             if (descriptor == null) {
890                 throw QueryException.invalidExpressionForQueryItem(expression, this);
891             }
892         } else if (mapping.isAggregateObjectMapping()) {
893             descriptor = ((AggregateObjectMapping)mapping).getReferenceDescriptor();
894         } else if (mapping.isForeignReferenceMapping()) {
895             descriptor = ((ForeignReferenceMapping)mapping).getReferenceDescriptor();
896         }
897         return descriptor;
898     }
899
900     /**
901      * PUBLIC:
902      * Return the current locking mode.
903      */

904     public short getLockMode() {
905         if (lockingClause == null) {
906             return DEFAULT_LOCK_MODE;
907         } else {
908             return lockingClause.getLockMode();
909         }
910     }
911
912     /**
913      * INTERNAL:
914      * It is not exactly as simple as a query being either locking or not.
915      * Any combination of the reference class object and joined attributes
916      * may be locked.
917      */

918     public ForUpdateClause getLockingClause() {
919         return lockingClause;
920     }
921
922     /**
923      * INTERNAL:
924      * Return the time this query actually went to the database
925      */

926     public long getExecutionTime() {
927         return executionTime;
928     }
929
930     /**
931      * PUBLIC:
932      * Return the reference class of the query.
933      */

934     // TODO This method is left in so the javadoc remains, but is actually implemented on
935
// super. We should reconsider this.
936
public Class JavaDoc getReferenceClass() {
937         return super.getReferenceClass();
938     }
939
940     /**
941      * INTERNAL:
942      * Return the reference class of the query.
943      */

944      // TODO This method is left in so the javadoc remains, but is actually implemented on
945
// super. We should reconsider this.
946
public String JavaDoc getReferenceClassName() {
947         return super.getReferenceClassName();
948     }
949
950     /**
951      * PUBLIC:
952      * Answers if the domain objects are to be read as of a past time.
953      * @see #getAsOfClause()
954      */

955     public boolean hasAsOfClause() {
956         return ((defaultBuilder != null) && defaultBuilder.hasAsOfClause());
957     }
958
959     /**
960      * INTERNAL:
961      * Return the attributes that must be joined.
962      */

963     public boolean hasNonFetchJoinedAttributeExpressions() {
964         return this.nonFetchJoinAttributeExpressions != null && !this.nonFetchJoinAttributeExpressions.isEmpty();
965     }
966
967     /**
968      * INTERNAL:
969      * Return if partial attributes.
970      */

971     public boolean hasPartialAttributeExpressions() {
972         return false;
973     }
974
975     /**
976      * INTERNAL:
977      * Return the fields selected by the query.
978      * This includes the partial or joined fields.
979      * This is used for custom SQL executions.
980      */

981     public Vector getSelectionFields() {
982         if ((!hasPartialAttributeExpressions()) && (!getJoinedAttributeManager().hasJoinedAttributes()) && (!hasFetchGroupAttributeExpressions())) {
983             return getDescriptor().getAllFields();
984         }
985         Vector fields;
986         if (hasFetchGroupAttributeExpressions()) {//fetch group support
987
List fetchGroupAttrExps = getFetchGroup().getFetchGroupAttributeExpressions();
988             fields = new Vector(fetchGroupAttrExps.size());
989             for (int index = 0; index < fetchGroupAttrExps.size(); index++) {
990                 Expression expression = (Expression)fetchGroupAttrExps.get(index);
991
992                 // Expression may not have been initialized.
993
expression.getBuilder().setSession(getSession());
994                 expression.getBuilder().setQueryClass(getReferenceClass());
995                 Helper.addAllToVector(fields, expression.getFields());
996             }
997         } else {
998             fields = new Vector(getDescriptor().getAllFields().size() + getJoinedAttributeManager().getJoinedAttributeExpressions().size() + getJoinedAttributeManager().getJoinedMappingExpressions().size());
999             Helper.addAllToVector(fields, getDescriptor().getAllFields());
1000            addSelectionFieldsForJoinedExpressions(fields, getJoinedAttributeManager().getJoinedAttributeExpressions());
1001            addSelectionFieldsForJoinedExpressions(fields, getJoinedAttributeManager().getJoinedMappingExpressions());
1002        }
1003        return fields;
1004    }
1005
1006    /**
1007     * Initialize the expression builder which should be used for this query. If
1008     * there is a where clause, use its expression builder, otherwise
1009     * generate one and cache it. This helps avoid unnecessary rebuilds.
1010     */

1011    protected void initializeDefaultBuilder() {
1012        DatabaseQueryMechanism mech = getQueryMechanism();
1013        if (mech.isExpressionQueryMechanism() && ((ExpressionQueryMechanism)mech).getExpressionBuilder() != null) {
1014            this.defaultBuilder = ((ExpressionQueryMechanism)mech).getExpressionBuilder();
1015            return;
1016        }
1017        this.defaultBuilder = new ExpressionBuilder();
1018    }
1019
1020    /**
1021     * INTERNAL:
1022     * return true if this query has computed its distinct value already
1023     */

1024    public boolean isDistinctComputed() {
1025        return getDistinctState() != UNCOMPUTED_DISTINCT;
1026    }
1027
1028    /**
1029     * PUBLIC:
1030     * Answers if the query lock mode is known to be LOCK or LOCK_NOWAIT.
1031     *
1032     * In the case of DEFAULT_LOCK_MODE and the query reference class being a CMP entity bean,
1033     * at execution time LOCK, LOCK_NOWAIT, or NO_LOCK will be decided.
1034     * <p>
1035     * If a single joined attribute was configured for pessimistic locking then
1036     * this will return true (after first execution) as the SQL contained a
1037     * FOR UPDATE OF clause.
1038     */

1039    public boolean isLockQuery() {
1040        return getLockMode() > NO_LOCK;
1041    }
1042
1043    /**
1044     * ADVANCED:
1045     * Answers if this query will issue any pessimistic locks.
1046     * <p>
1047     * If the lock mode is not known (DEFAULT_LOCK_MODE / descriptor specified
1048     * fine-grained locking) the lock mode will be determined now, to be either
1049     * LOCK, LOCK_NOWAIT, or NO_LOCK.
1050     * @see #isLockQuery()
1051     */

1052    public boolean isLockQuery(oracle.toplink.essentials.sessions.Session session) {
1053        checkPrePrepare((AbstractSession)session);
1054        return isLockQuery();
1055    }
1056
1057    /**
1058     * PUBLIC:
1059     * Return if this is an object level read query.
1060     */

1061    public boolean isObjectLevelReadQuery() {
1062        return true;
1063    }
1064
1065    /**
1066     * PUBLIC:
1067     * Queries prepare common stated in themselves.
1068     */

1069    protected boolean isPrePrepared() {
1070        return isPrePrepared;
1071    }
1072
1073    /**
1074     * INTERNAL:
1075     * Answers if we are executing through a UnitOfWork and registering results.
1076     * This is only ever false if using the conforming without registering
1077     * feature.
1078     */

1079    protected boolean isRegisteringResults() {
1080        return ((shouldRegisterResultsInUnitOfWork() && getDescriptor().shouldRegisterResultsInUnitOfWork()) || isLockQuery());
1081    }
1082
1083    /**
1084     * INTERNAL:
1085     * If changes are made to the query that affect the derived SQL or Call
1086     * parameters the query needs to be prepared again.
1087     * <p>
1088     * Automatically called internally.
1089     * <p>
1090     * The early phase of preparation is to check if this is a pessimistic
1091     * locking query.
1092     */

1093    protected void setIsPrePrepared(boolean isPrePrepared) {
1094        // Only unprepare if was prepared to begin with, prevent unpreparing during prepare.
1095
if (this.isPrePrepared && !isPrePrepared) {
1096            setIsPrepared(false);
1097            this.getJoinedAttributeManager().reset();
1098        }
1099        this.isPrePrepared = isPrePrepared;
1100    }
1101
1102    /**
1103     * INTERNAL:
1104     * Prepare the receiver for execution in a session.
1105     */

1106    protected void prepare() throws QueryException {
1107        super.prepare();
1108        prepareQuery();
1109    }
1110
1111    /**
1112     * INTERNAL:
1113     * Prepare the receiver for execution in a session.
1114     */

1115    protected void prePrepare() throws QueryException {
1116        // For bug 3136413/2610803 building the selection criteria from an EJBQL string or
1117
// an example object is done just in time.
1118
buildSelectionCriteria(session);
1119        checkDescriptor(session);
1120
1121        // Add mapping joined attributes.
1122
if (getQueryMechanism().isExpressionQueryMechanism()) {
1123            getJoinedAttributeManager().processJoinedMappings();
1124        }
1125
1126        // modify query for locking only if locking has not been configured
1127
if (isDefaultLock()) {
1128            setWasDefaultLockMode(true);
1129            ForUpdateOfClause lockingClause = null;
1130            if (getJoinedAttributeManager().hasJoinedExpressions()) {
1131                lockingClause = getJoinedAttributeManager().setupLockingClauseForJoinedExpressions(lockingClause, getSession());
1132            }
1133            if (lockingClause == null) {
1134                this.lockingClause = ForUpdateClause.newInstance(NO_LOCK);
1135            } else {
1136                this.lockingClause = lockingClause;
1137                // SPECJ: Locking not compatible with distinct for batch reading.
1138
dontUseDistinct();
1139            }
1140        } else if (getLockMode() == NO_LOCK) {
1141            setWasDefaultLockMode(true);
1142        }
1143    }
1144
1145    /**
1146     * INTERNAL:
1147     * Prepare the receiver for execution in a session.
1148     */

1149    protected void prepareQuery() throws QueryException {
1150        if ((!shouldMaintainCache()) && shouldRefreshIdentityMapResult() && (!descriptor.isAggregateCollectionDescriptor())) {
1151            throw QueryException.refreshNotPossibleWithoutCache(this);
1152        }
1153        if (shouldMaintainCache() && hasPartialAttributeExpressions()) {
1154            throw QueryException.cannotCachePartialObjects(this);
1155        }
1156
1157        if (descriptor.isAggregateDescriptor()) {
1158            // Not allowed
1159
throw QueryException.aggregateObjectCannotBeDeletedOrWritten(descriptor, this);
1160        }
1161
1162        // If fetch group manager is not set in the descriptor and the user attempts to use fetch group in the query dynamiclly, throw exception here.
1163
if ((!getDescriptor().hasFetchGroupManager()) && ((getFetchGroup() != null) || (getFetchGroupName() != null))) {
1164            throw QueryException.fetchGroupValidOnlyIfFetchGroupManagerInDescriptor(getDescriptor().getJavaClassName(), getName());
1165        }
1166
1167        // Prepare fetch group if applied.
1168
if (getDescriptor().hasFetchGroupManager()) {
1169            getDescriptor().getFetchGroupManager().prepareQueryWithFetchGroup(this);
1170        }
1171
1172        // Validate and prepare join expressions.
1173
if (getJoinedAttributeManager().hasJoinedExpressions()) {
1174            getJoinedAttributeManager().prepareJoinExpressions(getSession());
1175        } else {
1176            // If the query is being re-prepared must clear possible old cached data.
1177
getJoinedAttributeManager().reset();
1178        }
1179    }
1180
1181    /**
1182     * PUBLIC:
1183     * Refresh the attributes of the object(s) resulting from the query.
1184     * If cascading is used the private parts of the objects will also be refreshed.
1185     */

1186    public void refreshIdentityMapResult() {
1187        setShouldRefreshIdentityMapResult(true);
1188    }
1189
1190    /**
1191     * INTERNAL:
1192     * All objects queried via a UnitOfWork get registered here. If the query
1193     * went to the database.
1194     * <p>
1195     * Involves registering the query result individually and in totality, and
1196     * hence refreshing / conforming is done here.
1197     *
1198     * @param result may be collection (read all) or an object (read one),
1199     * or even a cursor. If in transaction the shared cache will
1200     * be bypassed, meaning the result may not be originals from the parent
1201     * but raw database rows.
1202     * @param unitOfWork the unitOfWork the result is being registered in.
1203     * @param arguments the original arguments/parameters passed to the query
1204     * execution. Used by conforming
1205     * @param buildDirectlyFromRows If in transaction must construct
1206     * a registered result from raw database rows.
1207     *
1208     * @return the final (conformed, refreshed, wrapped) UnitOfWork query result
1209     */

1210    public abstract Object JavaDoc registerResultInUnitOfWork(Object JavaDoc result, UnitOfWorkImpl unitOfWork, AbstractRecord arguments, boolean buildDirectlyFromRows);
1211
1212    /**
1213     * ADVANCED:
1214     * If a distinct has been set the DISTINCT clause will be printed.
1215     * This is used internally by TopLink for batch reading but may also be
1216     * used directly for advanced queries or report queries.
1217     */

1218    public void resetDistinct() {
1219        setDistinctState(UNCOMPUTED_DISTINCT);
1220        //Bug2804042 Must un-prepare if prepared as the SQL may change.
1221
setIsPrepared(false);
1222    }
1223
1224    /**
1225     * INTERNAL:
1226     * Additional fields can be added to a query. This is used in m-m bacth reading to bring back the key from the join table.
1227     */

1228    public void setAdditionalFields(Vector additionalFields) {
1229        this.additionalFields = additionalFields;
1230    }
1231
1232    /**
1233     * PUBLIC:
1234     * Set the cache usage.
1235     * By default only primary key read object queries will first check the cache before accessing the database.
1236     * Any query can be configure to query against the cache completely, by key or ignore the cache check.
1237     * <p>Valid values are:
1238     * <ul>
1239     * <li> DoNotCheckCache - The query does not check the cache but accesses the database, the cache will still be maintain.
1240     * <li> CheckCacheByExactPrimaryKey - If the query is exactly and only on the object's primary key the cache will be checked.
1241     * <li> CheckCacheByPrimaryKey - If the query contains the primary key and possible other values the cache will be checked.
1242     * <li> CheckCacheThenDatabase - The whole cache will be checked to see if there is any object matching the query, if not the database will be accessed.
1243     * <li> CheckCacheOnly - The whole cache will be checked to see if there is any object matching the query, if not null or an empty collection is returned.
1244     * <li> ConformResultsAgainstUnitOfWork - The results will be checked againtst the changes within the unit of work and object no longer matching or deleted will be remove, matching new objects will also be added.
1245     * <li> shouldCheckDescriptorForCacheUsage - This setting functions like CheckCacheByPrimaryKey, except checks the appropriate descriptor's
1246     * shouldDisableCacheHits setting when querying on the cache.
1247      * </lu>
1248     */

1249    public void setCacheUsage(int cacheUsage) {
1250        this.cacheUsage = cacheUsage;
1251    }
1252
1253    /**
1254     * INTERNAL:
1255     * Set the descriptor for the query.
1256     */

1257    public void setDescriptor(ClassDescriptor descriptor) {
1258        super.setDescriptor(descriptor);
1259        if (this.joinedAttributeManager != null){
1260            this.joinedAttributeManager.setDescriptor(descriptor);
1261        }
1262    }
1263
1264    /**
1265     * ADVANCED:
1266     * If a distinct has been set the DISTINCT clause will be printed.
1267     * This is used internally by TopLink for batch reading but may also be
1268     * used directly for advanced queries or report queries.
1269     */

1270    public void setDistinctState(short distinctState) {
1271        this.distinctState = distinctState;
1272    }
1273
1274    /**
1275     * INTERNAL:
1276     * Set the the time this query went to the database.
1277     */

1278    public void setExecutionTime(long executionTime) {
1279        this.executionTime = executionTime;
1280    }
1281
1282    /**
1283     * PUBLIC:
1284     * Set the InMemoryQueryIndirectionPolicy for this query
1285     */

1286    //Feature 2297
1287
public void setInMemoryQueryIndirectionPolicy(InMemoryQueryIndirectionPolicy inMemoryQueryIndirectionPolicy) {
1288        //Bug2862302 Backwards compatibility. This makes sure 9.0.3 and any older version project xml don't break
1289
if (inMemoryQueryIndirectionPolicy != null) {
1290            this.inMemoryQueryIndirectionPolicy = inMemoryQueryIndirectionPolicy;
1291        }
1292    }
1293
1294    /**
1295     * PUBLIC:
1296     * Sets whether this is a pessimistically locking query.
1297     * <ul>
1298     * <li>ObjectBuildingQuery.LOCK: SELECT .... FOR UPDATE issued.
1299     * <li>ObjectBuildingQuery.LOCK_NOWAIT: SELECT .... FOR UPDATE NO WAIT issued.
1300     * <li>ObjectBuildingQuery.NO_LOCK: no pessimistic locking.
1301     * <li>ObjectBuildingQuery.DEFAULT_LOCK_MODE (default) and you have a CMP descriptor:
1302     * fine grained locking will occur.
1303     * </ul>
1304     * <p>Fine Grained Locking: On execution the reference class
1305     * and those of all joined attributes will be checked. If any of these have a
1306     * PessimisticLockingPolicy set on their descriptor, they will be locked in a
1307     * SELECT ... FOR UPDATE OF ... {NO WAIT}. Issues fewer locks
1308     * and avoids setting the lock mode on each query.
1309     * <p>Example:<code>readAllQuery.setSelectionCriteria(employee.get("address").equal("Ottawa"));</code>
1310     * <ul><li>LOCK: all employees in Ottawa and all referenced Ottawa addresses will be locked.
1311     * <li>DEFAULT_LOCK_MODE: if address is a joined attribute, and only address has a pessimistic
1312     * locking policy, only referenced Ottawa addresses will be locked.
1313     * </ul>
1314     * @see oracle.toplink.essentials.descriptors.PessimisticLockingPolicy
1315     */

1316    public void setLockMode(short lockMode) {
1317        if ((lockMode == LOCK) || (lockMode == LOCK_NOWAIT)) {
1318            lockingClause = ForUpdateClause.newInstance(lockMode);
1319            setShouldRefreshIdentityMapResult(true);
1320        } else if (lockMode == NO_LOCK) {
1321            lockingClause = ForUpdateClause.newInstance(lockMode);
1322        } else {
1323            lockingClause = null;
1324            setIsPrePrepared(false);
1325        }
1326        setIsPrepared(false);
1327    }
1328
1329    /**
1330     * INTERNAL:
1331     * Return the attributes that must be joined, but not fetched, that is,
1332     * do not trigger the value holder.
1333     */

1334    protected void setNonFetchJoinAttributeExpressions(Vector nonFetchJoinExpressions) {
1335        this.nonFetchJoinAttributeExpressions = nonFetchJoinExpressions;
1336    }
1337
1338    /**
1339     * INTERNAL:
1340     * The locking clause contains a list of expressions representing which
1341     * objects are to be locked by the query.
1342     * <p>
1343     * Use for even finer grained control over what is and is not locked by
1344     * a particular query.
1345     */

1346    public void setLockingClause(ForUpdateClause clause) {
1347        if (clause.isForUpdateOfClause()) {
1348            this.lockingClause = clause;
1349            setIsPrePrepared(false);
1350        } else {
1351            setLockMode(clause.getLockMode());
1352        }
1353    }
1354
1355    public void setEJBQLString(String JavaDoc ejbqlString) {
1356        super.setEJBQLString(ejbqlString);
1357        setIsPrePrepared(false);
1358    }
1359
1360    /**
1361     * REQUIRED:
1362     * Set the reference class for the query.
1363     */

1364    // TODO This method is left in so the javadoc remains, but is actually implemented on
1365
// super. We should reconsider this.
1366
public void setReferenceClass(Class JavaDoc aClass) {
1367        super.setReferenceClass(aClass);
1368    }
1369
1370    /**
1371     * INTERNAL:
1372     * Set the reference class for the query.
1373     */

1374    // TODO This method is left in so the javadoc remains, but is actually implemented on
1375
// super. We should reconsider this.
1376
public void setReferenceClassName(String JavaDoc aClass) {
1377        super.setReferenceClassName(aClass);
1378    }
1379
1380    public void setSelectionCriteria(Expression expression) {
1381        super.setSelectionCriteria(expression);
1382        if ((expression != null) && (defaultBuilder != null)) {
1383            // For flashback: Must make sure expression and defaultBuilder always in sync.
1384
ExpressionBuilder newBuilder = expression.getBuilder();
1385            if ( (newBuilder != defaultBuilder) && (newBuilder.getQueryClass() == null || newBuilder.getQueryClass().equals(defaultBuilder.getQueryClass()) )){
1386                defaultBuilder = newBuilder;
1387            }
1388        }
1389    }
1390
1391    /**
1392     * INTERNAL:
1393     * Set if the rows for the result of the query should also be returned using a complex query result.
1394     * @see ComplexQueryResult
1395     */

1396    public void setShouldIncludeData(boolean shouldIncludeData) {
1397        this.shouldIncludeData = shouldIncludeData;
1398    }
1399
1400    /**
1401     * PUBLIC:
1402     * Set if the attributes of the object(s) resulting from the query should be refreshed.
1403     * If cascading is used the private parts of the objects will also be refreshed.
1404     */

1405    public void setShouldRefreshIdentityMapResult(boolean shouldRefreshIdentityMapResult) {
1406        this.shouldRefreshIdentityMapResult = shouldRefreshIdentityMapResult;
1407    }
1408
1409    /**
1410     * INTERNAL:
1411     * Set to false to have queries conform to a UnitOfWork without registering
1412     * any additional objects not already in that UnitOfWork.
1413     * @see #shouldRegisterResultsInUnitOfWork
1414     * @bug 2612601
1415     */

1416    public void setShouldRegisterResultsInUnitOfWork(boolean shouldRegisterResultsInUnitOfWork) {
1417        this.shouldRegisterResultsInUnitOfWork = shouldRegisterResultsInUnitOfWork;
1418    }
1419
1420    /**
1421     * PUBLIC:
1422     * Return if cache should be checked.
1423     */

1424    public boolean shouldCheckCacheOnly() {
1425        return getCacheUsage() == CheckCacheOnly;
1426    }
1427
1428    /**
1429     * PUBLIC:
1430     * Return whether the descriptor's disableCacheHits setting should be checked prior
1431     * to querying the cache.
1432     */

1433    public boolean shouldCheckDescriptorForCacheUsage() {
1434        return getCacheUsage() == UseDescriptorSetting;
1435    }
1436
1437    /**
1438     * PUBLIC:
1439     * Should the results will be checked against the changes within the unit of work and object no longer matching or deleted will be remove, matching new objects will also be added..
1440     */

1441    public boolean shouldConformResultsInUnitOfWork() {
1442        return getCacheUsage() == ConformResultsInUnitOfWork;
1443    }
1444
1445    /**
1446     * INTERNAL:
1447     * return true if this query should use a distinct
1448     */

1449    public boolean shouldDistinctBeUsed() {
1450        return getDistinctState() == USE_DISTINCT;
1451    }
1452
1453    /**
1454     * INTERNAL:
1455     * Return if the rows for the result of the query should also be returned using a complex query result.
1456     * @see ComplexQueryResult
1457     */

1458    public boolean shouldIncludeData() {
1459        return shouldIncludeData;
1460    }
1461
1462    /**
1463     * INTERNAL:
1464     * Allows one to do conforming in a UnitOfWork without registering.
1465     * Queries executed on a UnitOfWork will only return working copies for objects
1466     * that have already been registered.
1467     * <p>Extreme care should be taken in using this feature, for a user will
1468     * get back a mix of registered and original (unregistered) objects.
1469     * <p>Best used with a WrapperPolicy where invoking on an object will trigger
1470     * its registration (CMP). Without a WrapperPolicy {@link oracle.toplink.essentials.sessions.UnitOfWork#registerExistingObject registerExistingObject}
1471     * should be called on any object that you intend to change.
1472     * @return true by default.
1473     * @see #setShouldRegisterResultsInUnitOfWork(boolean)
1474     * @see oracle.toplink.essentials.publicinterface.Descriptor#shouldRegisterResultsInUnitOfWork()
1475     * @bug 2612601
1476     */

1477    public boolean shouldRegisterResultsInUnitOfWork() {
1478        return shouldRegisterResultsInUnitOfWork;
1479    }
1480
1481    /**
1482     * INTERNAL:
1483     * Return if this is a full object query, not partial nor fetch group.
1484     */

1485    public boolean shouldReadAllMappings() {
1486        return (!hasPartialAttributeExpressions()) && (!hasFetchGroupAttributeExpressions());
1487    }
1488    
1489    /**
1490     * INTERNAL:
1491     * Check if the mapping is part of the partial attributes.
1492     */

1493    public boolean shouldReadMapping(DatabaseMapping mapping) {
1494        if ((!hasPartialAttributeExpressions()) && (!hasFetchGroupAttributeExpressions())) {
1495            return true;
1496        }
1497
1498        // bug 3659145
1499
if (hasFetchGroupAttributeExpressions()) {
1500            return isFetchGroupAttribute(mapping.getAttributeName());
1501        }
1502
1503        return true;
1504    }
1505
1506    /**
1507     * PUBLIC:
1508     * Set to a boolean. When set means refresh the instance
1509     * variables of referenceObject from the database.
1510     */

1511    public boolean shouldRefreshIdentityMapResult() {
1512        return shouldRefreshIdentityMapResult;
1513    }
1514
1515    public String JavaDoc toString() {
1516        if (getReferenceClass() == null) {
1517            return super.toString();
1518        }
1519        return Helper.getShortClassName(getClass()) + "(" + getReferenceClass().getName() + ")";
1520    }
1521
1522    /**
1523     * ADVANCED:
1524     * Used for CMP only. This allows users to indicate whether cmp finders executed
1525     * at the beginning of a transaction should always be run against a UnitOfWork.
1526     * Defaults to true.
1527     * <p>
1528     * If set to false, then UnitOfWork allocation will be deferred until a business
1529     * method (including creates/removes) or finder with shouldProcessResultsInUnitOfWork == true
1530     * is invoked. Any finder executed before such a time, will do so against the
1531     * underlying ServerSession. Forcing finder execution to always go through a
1532     * UnitOfWork means the results will be cloned and cached in the UnitOfWork up
1533     * front. This is desired when the results will be accessed in the same transaction.
1534     * <p>
1535     * Note that finders executed with an unspecified transaction context will never
1536     * be executed against a UnitOfWork, even if this setting is true. This case may happen
1537     * with the NotSupported, Never, and Supports attributes.
1538     */

1539    public void setShouldProcessResultsInUnitOfWork(boolean processResultsInUnitOfWork) {
1540        this.shouldProcessResultsInUnitOfWork = processResultsInUnitOfWork;
1541    }
1542
1543    /**
1544     * ADVANCED:
1545     * Used for CMP only. Indicates whether cmp finders executed at the beginning
1546     * of a transaction should always be run against a UnitOfWork.
1547     * Defaults to true.
1548     * <p>
1549     * If set to false, then UnitOfWork allocation will be deferred until a business
1550     * method (including creates/removes) or finder with shouldProcessResultsInUnitOfWork == true
1551     * is invoked. Any finder executed before such a time, will do so against the
1552     * underlying ServerSession. Forcing finder execution to always go through a
1553     * UnitOfWork means the results will be cloned and cached in the UnitOfWork up
1554     * front. This is desired when the results will be accessed in the same transaction.
1555     * <p>
1556     * Note that finders executed with an unspecified transaction context will never
1557     * be executed against a UnitOfWork, even if this setting is true. This case may happen
1558     * with the NotSupported, Never, and Supports attributes.
1559     */

1560    public boolean shouldProcessResultsInUnitOfWork() {
1561        return this.shouldProcessResultsInUnitOfWork;
1562    }
1563
1564    /**
1565     * ADVANCED:
1566     * If a distinct has been set the DISTINCT clause will be printed.
1567     * This is used internally by TopLink for batch reading but may also be
1568     * used directly for advanced queries or report queries.
1569     */

1570    public void useDistinct() {
1571        setDistinctState(USE_DISTINCT);
1572        //Bug2804042 Must un-prepare if prepared as the SQL may change.
1573
setIsPrepared(false);
1574    }
1575
1576    /**
1577    * INTERNAL:
1578    * Helper method that checks if clone has been locked with uow.
1579    */

1580    public boolean isClonePessimisticLocked(Object JavaDoc clone, UnitOfWorkImpl uow) {
1581        return false;
1582    }
1583
1584    /**
1585     * INTERNAL:
1586     * Helper method that records clone with uow if query is pessimistic locking.
1587     */

1588    public void recordCloneForPessimisticLocking(Object JavaDoc clone, UnitOfWorkImpl uow) {
1589        if ((isLockQuery()) && lockingClause.isReferenceClassLocked()) {
1590            uow.addPessimisticLockedClone(clone);
1591        }
1592    }
1593
1594    /**
1595    * INTERNAL: Helper method to determine the default mode. If true and quey has a pessimistic locking policy,
1596    * locking will be configured according to the pessimistic locking policy.
1597    */

1598    public boolean isDefaultLock() {
1599        return (lockingClause == null);
1600    }
1601
1602    /**
1603     * Return the fetch group set in the query.
1604     * If a fetch group is not explicitly set in the query, default fetch group optionally defined in the decsiptor
1605     * would be used, unless the user explicitly calls query.setShouldUseDefaultFetchGroup(false).
1606     */

1607    public FetchGroup getFetchGroup() {
1608        return fetchGroup;
1609    }
1610
1611    /**
1612     * INTERNAL:
1613     * Initialize fetch group
1614     */

1615    public void initializeFetchGroup() {
1616        if (fetchGroup != null) {
1617            //fetch group already set.
1618
return;
1619        }
1620
1621        //not explicitly set dynamically fetch group
1622
if (fetchGroupName != null) {//set pre-defined named group
1623
fetchGroup = getDescriptor().getFetchGroupManager().getFetchGroup(fetchGroupName);
1624            if (fetchGroup == null) {
1625                //named fetch group is not defined in the descriptor
1626
throw QueryException.fetchGroupNotDefinedInDescriptor(fetchGroupName);
1627            }
1628        } else {//not set fecth group at all
1629
//use the default fetch group if not explicitly turned off
1630
if (shouldUseDefaultFetchGroup()) {
1631                fetchGroup = getDescriptor().getDefaultFetchGroup();
1632            }
1633        }
1634    }
1635
1636    /**
1637     * Set a dynamic (use case) fetch group to the query.
1638     */

1639    public void setFetchGroup(FetchGroup newFetchGroup) {
1640        fetchGroup = newFetchGroup;
1641    }
1642
1643    /**
1644     * Set a descriptor-level pre-defined named fetch group to the query.
1645     */

1646    public void setFetchGroupName(String JavaDoc groupName) {
1647        //nullify the fecth group refernce as one query can only has one fetch group.
1648
fetchGroup = null;
1649        fetchGroupName = groupName;
1650    }
1651
1652    /**
1653     * Return the fetch group name set in the query.
1654     */

1655    public String JavaDoc getFetchGroupName() {
1656        return fetchGroupName;
1657    }
1658
1659    /**
1660     * Return false if the query does not use the default fetch group defined in the descriptor level.
1661     */

1662    public boolean shouldUseDefaultFetchGroup() {
1663        return shouldUseDefaultFetchGroup;
1664    }
1665
1666    /**
1667     * Set false if the user does not want to use the default fetch group defined in the descriptor level.
1668     */

1669    public void setShouldUseDefaultFetchGroup(boolean shouldUseDefaultFetchGroup) {
1670        this.shouldUseDefaultFetchGroup = shouldUseDefaultFetchGroup;
1671    }
1672
1673    /**
1674     * INTERNAL:
1675     * Return if fetch group attributes.
1676     */

1677    public boolean hasFetchGroupAttributeExpressions() {
1678        return (getFetchGroup() != null) && (getFetchGroup().hasFetchGroupAttributeExpressions());
1679    }
1680
1681    /**
1682     * INTERNAL:
1683     * Return if fetch group attribute.
1684     */

1685    public boolean isFetchGroupAttribute(String JavaDoc attributeName) {
1686        if (getFetchGroup() == null) {
1687            //every attribute is fetched already
1688
return true;
1689        }
1690        return getFetchGroup().getAttributes().contains(attributeName);
1691    }
1692}
1693
Popular Tags