KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > queryframework > DatabaseQueryMechanism


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.internal.queryframework;
23
24 import java.util.*;
25 import java.io.*;
26 import oracle.toplink.essentials.internal.descriptors.OptimisticLockingPolicy;
27 import oracle.toplink.essentials.descriptors.VersionLockingPolicy;
28 import oracle.toplink.essentials.descriptors.DescriptorEvent;
29 import oracle.toplink.essentials.descriptors.DescriptorEventManager;
30 import oracle.toplink.essentials.descriptors.DescriptorQueryManager;
31 import oracle.toplink.essentials.internal.helper.*;
32 import oracle.toplink.essentials.internal.databaseaccess.*;
33 import oracle.toplink.essentials.internal.sessions.*;
34 import oracle.toplink.essentials.sessions.DatabaseRecord;
35 import oracle.toplink.essentials.internal.identitymaps.CacheKey;
36 import oracle.toplink.essentials.expressions.*;
37 import oracle.toplink.essentials.queryframework.*;
38 import oracle.toplink.essentials.exceptions.*;
39 import oracle.toplink.essentials.mappings.*;
40 import oracle.toplink.essentials.logging.SessionLog;
41 import oracle.toplink.essentials.internal.sessions.AbstractRecord;
42 import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl;
43 import oracle.toplink.essentials.internal.sessions.AbstractSession;
44 import oracle.toplink.essentials.descriptors.ClassDescriptor;
45
46 /**
47  * <p><b>Purpose</b>:
48  * Abstract class for all database query mechanism objects.
49  * DatabaseQueryMechanism is actually a helper class and currently is required
50  * for all types of queries. Most of the work performed by the query framework is
51  * performed in the query mechanism. The query mechanism contains the internal
52  * knowledge necessary to perform the specific database operation.
53  * <p>
54  * <p><b>Responsibilities</b>:
55  * Provide a common protocol for query mechanism objects.
56  * Provides all of the database specific work for the assigned query.
57  *
58  * @author Yvon Lavoie
59  * @since TOPLink/Java 1.0
60  */

61 public abstract class DatabaseQueryMechanism implements Cloneable JavaDoc, Serializable {
62
63     /** The database query that uses this mechanism. */
64     protected DatabaseQuery query;
65
66     /**
67      * Initialize the state of the query.
68      */

69     public DatabaseQueryMechanism() {
70     }
71
72     /**
73      * Initialize the state of the query
74      * @param query - owner of mechanism
75      */

76     public DatabaseQueryMechanism(DatabaseQuery query) {
77         this.query = query;
78     }
79
80     /**
81      * Add the initial write lock value to the row for insert.
82      */

83     protected void addWriteLockFieldForInsert() {
84         if (getDescriptor().usesOptimisticLocking()) {
85             getDescriptor().getOptimisticLockingPolicy().setupWriteFieldsForInsert(getWriteObjectQuery());
86         }
87     }
88
89     /**
90      * Internal:
91      * In the case of EJBQL, an expression needs to be generated. Build the required expression.
92      */

93     public void buildSelectionCriteria(AbstractSession session) {
94         // Default is do nothing
95
}
96
97     /**
98      * Perform a cache lookup for the query.
99      * If the translation row contains all the primary key fields,
100      * then a cache check will be performed.
101      * If the object is found in the cache, return it;
102      * otherwise return null.
103      */

104     public Object JavaDoc checkCacheForObject(AbstractRecord translationRow, AbstractSession session) {
105         // Null check added for CR#4295 - TW
106
if ((translationRow == null) || (translationRow.isEmpty())) {
107             return null;
108         }
109
110         List keyFields = getDescriptor().getPrimaryKeyFields();
111         Vector primaryKey = new Vector(keyFields.size());
112
113         for (int index = 0; index < keyFields.size(); index++) {
114             Object JavaDoc value = translationRow.get((DatabaseField)keyFields.get(index));
115             if (value == null) {
116                 return null;
117             } else {
118                 primaryKey.add(value);
119             }
120         }
121         return session.getIdentityMapAccessorInstance().getFromIdentityMapWithDeferredLock(primaryKey, getReadObjectQuery().getReferenceClass(), false, getDescriptor());
122     }
123
124     /**
125      * Clone the mechanism
126      */

127     protected Object JavaDoc clone() {
128         try {
129             return super.clone();
130         } catch (CloneNotSupportedException JavaDoc e) {
131             throw new InternalError JavaDoc();
132         }
133     }
134
135     /**
136      * Clone the mechanism for the specified query clone.
137      */

138     public DatabaseQueryMechanism clone(DatabaseQuery queryClone) {
139         DatabaseQueryMechanism clone = (DatabaseQueryMechanism)clone();
140         clone.setQuery(queryClone);
141         return clone;
142     }
143
144     /**
145      * Read all rows from the database using a cursored stream.
146      * @exception DatabaseException - an error has occurred on the database
147      */

148     public abstract DatabaseCall cursorSelectAllRows() throws DatabaseException;
149
150     /**
151      * Delete a collection of objects
152      * This should be overriden by subclasses.
153      * @exception DatabaseException - an error has occurred on the database
154      */

155     public boolean isEJBQLCallQueryMechanism() {
156         return false;
157     }
158
159     /**
160      * Build the objects for the rows, and answer them
161      * @exception DatabaseException - an error has occurred on the database
162      */

163     public Object JavaDoc buildObjectsFromRows(Vector rows) throws DatabaseException {
164         Object JavaDoc result = ((ReadAllQuery)getQuery()).getContainerPolicy().containerInstance(rows.size());
165         return getDescriptor().getObjectBuilder().buildObjectsInto((ReadAllQuery)getQuery(), rows, result);
166     }
167     ;
168     public abstract Integer JavaDoc deleteAll() throws DatabaseException;
169
170     /**
171      * Delete an object
172      * This should be overriden by subclasses.
173      * @exception DatabaseException
174      * @return the row count.
175      */

176     public abstract Integer JavaDoc deleteObject() throws DatabaseException;
177
178     /**
179      * Execute a non selecting SQL call
180      * This should be overriden by subclasses.
181      * @exception DatabaseException
182      * @return the row count.
183      */

184     public abstract Integer JavaDoc executeNoSelect() throws DatabaseException;
185
186     /**
187      * Execute a select SQL call and return the rows.
188      * This should be overriden by subclasses.
189      * @exception DatabaseException
190      */

191     public abstract Vector executeSelect() throws DatabaseException;
192
193     /**
194      * Check whether the object already exists on the database; then
195      * perform an insert or update, as appropriate.
196      * This method was moved here, from WriteObjectQuery.execute(),
197      * so we can hide the source.
198      * Return the object being written.
199      */

200     public Object JavaDoc executeWrite() throws DatabaseException, OptimisticLockException {
201         WriteObjectQuery writeQuery = getWriteObjectQuery();
202         Object JavaDoc object = writeQuery.getObject();
203         CommitManager commitManager = getSession().getCommitManager();
204
205         // if the object has already been committed, no work is required
206
if (commitManager.isCommitCompleted(object) || commitManager.isCommitInPostModify(object)) {
207             return object;
208         }
209
210         // check whether the object is already being committed -
211
// if it is and it is new, then a shallow insert must be done
212
if (commitManager.isCommitInPreModify(object)) {
213             shallowInsertObjectForWrite(object, writeQuery, commitManager);
214             return object;
215         }
216
217         try {
218             getSession().beginTransaction();
219
220             if (writeQuery.getObjectChangeSet() == null) {
221                 // PERF: Avoid events if no listeners.
222
if (getDescriptor().getEventManager().hasAnyEventListeners()) {
223                     // only throw the events if there is no changeset otherwise the event will be thrown twice
224
// once by the calculate changes code and here
225
getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PreWriteEvent, writeQuery));
226                 }
227             }
228             writeQuery.executeCommit();
229
230             // PERF: Avoid events if no listeners.
231
if (getDescriptor().getEventManager().hasAnyEventListeners()) {
232                 getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostWriteEvent, writeQuery));
233             }
234
235             getSession().commitTransaction();
236
237             // notify the commit manager of the completion to the commit
238
commitManager.markCommitCompleted(object);
239
240             return object;
241
242         } catch (RuntimeException JavaDoc exception) {
243             getSession().rollbackTransaction();
244             commitManager.markCommitCompleted(object);
245             throw exception;
246         }
247     }
248
249     /**
250      * Check whether the object already exists on the database; then
251      * perform an insert or update, as appropriate.
252      * This method was moved here, from WriteObjectQuery.execute(),
253      * so we can hide the source.
254      * Return the object being written.
255      */

256     public Object JavaDoc executeWriteWithChangeSet() throws DatabaseException, OptimisticLockException {
257         WriteObjectQuery writeQuery = getWriteObjectQuery();
258         ObjectChangeSet objectChangeSet = writeQuery.getObjectChangeSet();
259         CommitManager commitManager = getSession().getCommitManager();
260
261         //if there are no changes then there is no work required
262
// Check for forcedUpdate Version and Optimistic read lock (hasForcedChanges() set in ObjectChangePolicy)
263
if (!objectChangeSet.hasChanges() && !objectChangeSet.hasForcedChanges()) {
264             commitManager.markCommitCompleted(objectChangeSet);
265             commitManager.markCommitCompleted(writeQuery.getObject());
266             return writeQuery.getObject();
267         }
268     // if the object has already been committed, no work is required
269
if (commitManager.isCommitCompleted(objectChangeSet)
270             || commitManager.isCommitInPostModify(objectChangeSet)) {
271         return writeQuery.getObject();
272     }
273
274     // if the object has already been committed, no work is required
275
// need to check for the object to ensure insert wasn't completed already.
276
if (commitManager.isCommitCompleted(writeQuery.getObject())
277             || commitManager.isCommitInPostModify(writeQuery.getObject())) {
278             return writeQuery.getObject();
279         }
280         try {
281             getSession().beginTransaction();
282
283             writeQuery.executeCommitWithChangeSet();
284
285             // PERF: Avoid events if no listeners.
286
if (getDescriptor().getEventManager().hasAnyEventListeners()) {
287                 getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostWriteEvent, writeQuery));
288             }
289
290             getSession().commitTransaction();
291
292             // notify the commit manager of the completion to the commit
293
commitManager.markCommitCompleted(objectChangeSet);
294             commitManager.markCommitCompleted(writeQuery.getObject());
295
296             return writeQuery.getObject();
297
298         } catch (RuntimeException JavaDoc exception) {
299             getSession().rollbackTransaction();
300             commitManager.markCommitCompleted(objectChangeSet);
301             commitManager.markCommitCompleted(writeQuery.getObject());
302             throw exception;
303         }
304     }
305
306     /**
307      * Convenience method
308      */

309     protected ClassDescriptor getDescriptor() {
310         return getQuery().getDescriptor();
311     }
312
313     /**
314      * Convenience method
315      */

316     public AbstractRecord getModifyRow() {
317         if (getQuery().isModifyQuery()) {
318             return ((ModifyQuery)getQuery()).getModifyRow();
319         } else {
320             return null;
321         }
322     }
323
324     /**
325      * Return the query that uses the mechanism.
326      */

327     public DatabaseQuery getQuery() {
328         return query;
329     }
330
331     /**
332      * Convenience method
333      */

334     protected ReadObjectQuery getReadObjectQuery() {
335         return (ReadObjectQuery)getQuery();
336     }
337
338     /**
339      * Return the selection criteria for the mechanism.
340      * By default this is null. This method exists because both statement and expression
341      * mechanisms use an expression and some code in the mappings depends on returning this.
342      */

343     public Expression getSelectionCriteria() {
344         return null;
345     }
346
347     /**
348      * Convenience method
349      */

350     protected AbstractSession getSession() {
351         return getQuery().getSession();
352     }
353
354     /**
355      * Convenience method
356      */

357     protected AbstractRecord getTranslationRow() {
358         return getQuery().getTranslationRow();
359     }
360
361     /**
362      * Convenience method
363      */

364     protected WriteObjectQuery getWriteObjectQuery() {
365         return (WriteObjectQuery)getQuery();
366     }
367
368     /**
369      * Insert an object.
370      */

371     public abstract void insertObject() throws DatabaseException;
372
373     /**
374      * Insert an object and provide the opportunity to reprepare prior to the insert.
375      * This will be overridden
376      * CR#3237
377      */

378     public void insertObject(boolean reprepare) {
379         insertObject();
380     }
381
382     /**
383      * Insert an object in the database.
384      */

385     public void insertObjectForWrite() {
386         WriteObjectQuery writeQuery = getWriteObjectQuery();
387         Object JavaDoc object = writeQuery.getObject();
388         DescriptorQueryManager queryManager = getDescriptor().getQueryManager();
389
390         // check for user-defined query
391
if ((!writeQuery.isUserDefined())// this is not a user-defined query
392
&&queryManager.hasInsertQuery()// there is a user-defined query
393
&&isExpressionQueryMechanism()) {// this is not a hand-coded call (custom SQL etc.)
394
performUserDefinedInsert();
395             return;
396         }
397
398         CommitManager commitManager = getSession().getCommitManager();
399
400         // This must be done after the custom query check, otherwise it will be done twice.
401
commitManager.markPreModifyCommitInProgress(object);
402
403         if (writeQuery.getObjectChangeSet() == null) {
404             // PERF: Avoid events if no listeners.
405
if (getDescriptor().getEventManager().hasAnyEventListeners()) {
406                 // only throw the events if there is no changeset otherwise the event will be thrown twice
407
// once by the calculate changes code and here
408
getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PreInsertEvent, writeQuery));
409             }
410         }
411
412         // check whether deep shallow modify is turned on
413
if (writeQuery.shouldCascadeParts()) {
414             queryManager.preInsert(writeQuery);
415         }
416
417         // In a unit of work/writeObjects the preInsert may have caused a shallow insert of this object,
418
// in this case this second write must do an update.
419
if (commitManager.isShallowCommitted(object)) {
420             updateForeignKeyFieldAfterInsert();
421         } else {
422             AbstractRecord modifyRow = writeQuery.getModifyRow();
423             if (modifyRow == null) {// Maybe have been passed in as in aggregate collection.
424
if (writeQuery.shouldCascadeParts()) {
425                     writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRow(object, getSession()));
426                 } else {
427                     writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowForShallowInsert(object, getSession()));
428                 }
429             } else {
430                 if (writeQuery.shouldCascadeParts()) {
431                     writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRow(modifyRow, object, getSession()));
432                 } else {
433                     writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowForShallowInsert(modifyRow, object, getSession()));
434                 }
435             }
436
437             // the modify row and the translation row are the same for insert
438
writeQuery.setTranslationRow(getModifyRow());
439             if (!writeQuery.getDescriptor().isAggregateCollectionDescriptor()) {// Should/cannot be recomputed in aggregate collection.
440
writeQuery.setPrimaryKey(getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, getSession()));
441             }
442             addWriteLockFieldForInsert();
443
444             // CR#3237
445
// Store the size of the modify row so we can determine if the user has added to the row in the insert.
446
int modifyRowSize = getModifyRow().size();
447
448             // PERF: Avoid events if no listeners.
449
if (getDescriptor().getEventManager().hasAnyEventListeners()) {
450                 DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToInsertEvent, writeQuery);
451                 event.setRecord(getModifyRow());
452                 getDescriptor().getEventManager().executeEvent(event);
453             }
454
455             // CR#3237
456
// Call insert with a boolean that tells it to reprepare if the user has altered the modify row.
457
insertObject(modifyRowSize != getModifyRow().size());
458
459             // register the object before post insert to resolve possible cycles
460
registerObjectInIdentityMap();
461             if (writeQuery.getObjectChangeSet() != null) {
462                 //make sure that we put this new changeset in the changes list of the
463
//uow changeset for serialization, or customer usage.
464
((UnitOfWorkChangeSet)writeQuery.getObjectChangeSet().getUOWChangeSet()).putNewObjectInChangesList(writeQuery.getObjectChangeSet(), getSession());
465             }
466         }
467
468         commitManager.markPostModifyCommitInProgress(object);
469         // Verify if deep shallow modify is turned on.
470
if (writeQuery.shouldCascadeParts()) {
471             queryManager.postInsert(writeQuery);
472         }
473
474         // PERF: Avoid events if no listeners.
475
if (getDescriptor().getEventManager().hasAnyEventListeners()) {
476             getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostInsertEvent, writeQuery));
477         }
478     }
479
480     /**
481      * Insert an object in the database.
482      */

483     public void insertObjectForWriteWithChangeSet() {
484         WriteObjectQuery writeQuery = getWriteObjectQuery();
485         ObjectChangeSet objectChangeSet = writeQuery.getObjectChangeSet();
486         DescriptorQueryManager queryManager = getDescriptor().getQueryManager();
487         CommitManager commitManager = getSession().getCommitManager();
488
489         // check for user-defined query
490
if ((!writeQuery.isUserDefined())// this is not a user-defined query
491
&&queryManager.hasInsertQuery()// there is a user-defined query
492
&&isExpressionQueryMechanism()) {// this is not a hand-coded call (custom SQL etc.)
493
//must mark the changeSet here because the userDefined Insert will not use the changesets
494
commitManager.markPreModifyCommitInProgress(objectChangeSet);
495             performUserDefinedInsert();
496             return;
497         }
498
499         // This must be done after the custom query check, otherwise it will be done twice.
500
commitManager.markPreModifyCommitInProgress(objectChangeSet);
501         commitManager.markPreModifyCommitInProgress(writeQuery.getObject());
502
503         // check whether deep shallow modify is turned on
504
if (writeQuery.shouldCascadeParts()) {
505             queryManager.preInsert(writeQuery);
506         }
507
508         // In a unit of work/writeObjects the preInsert may have caused a shallow insert of this object,
509
// in this case this second write must do an update.
510
if (commitManager.isShallowCommitted(objectChangeSet)) {
511             updateForeignKeyFieldAfterInsert();
512         } else {
513             AbstractRecord modifyRow = writeQuery.getModifyRow();
514             if (modifyRow == null) {// Maybe have been passed in as in aggregate collection.
515
if (writeQuery.shouldCascadeParts()) {
516                     writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowWithChangeSet(objectChangeSet, getSession()));
517                 } else {
518                     writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowForShallowInsertWithChangeSet(objectChangeSet, getSession()));
519                 }
520             } else {
521                 if (writeQuery.shouldCascadeParts()) {
522                     writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowWithChangeSet(modifyRow, objectChangeSet, getSession()));
523                 } else {
524                     writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowForShallowInsertWithChangeSet(modifyRow, objectChangeSet, getSession()));
525                 }
526             }
527
528             // the modify row and the translation row are the same for insert
529
writeQuery.setTranslationRow(getModifyRow());
530             if (!writeQuery.getDescriptor().isAggregateCollectionDescriptor()) {// Should/cannot be recomputed in aggregate collection.
531
writeQuery.setPrimaryKey(objectChangeSet.getPrimaryKeys());
532             }
533             addWriteLockFieldForInsert();
534
535             // PERF: Avoid events if no listeners.
536
if (getDescriptor().getEventManager().hasAnyEventListeners()) {
537                 DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToInsertEvent, writeQuery);
538                 event.setRecord(getModifyRow());
539                 getDescriptor().getEventManager().executeEvent(event);
540             }
541
542             insertObject();
543
544             // register the object before post insert to resolve possible cycles
545
registerObjectInIdentityMap();
546             if (objectChangeSet != null) {
547                 //make sure that we put this new changeset in the changes list of the
548
//uow changeset for serialization, or customer usage.
549
((UnitOfWorkChangeSet)objectChangeSet.getUOWChangeSet()).putNewObjectInChangesList(objectChangeSet, getSession());
550             }
551         }
552
553         commitManager.markPostModifyCommitInProgress(objectChangeSet);
554         commitManager.markPostModifyCommitInProgress(writeQuery.getObject());
555         // Verify if deep shallow modify is turned on.
556
if (writeQuery.shouldCascadeParts()) {
557             queryManager.postInsert(writeQuery);
558         }
559
560         // PERF: Avoid events if no listeners.
561
if (getDescriptor().getEventManager().hasAnyEventListeners()) {
562             getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostInsertEvent, writeQuery));
563         }
564     }
565
566     /**
567      * Return true if this is a call query mechanism
568      */

569     public boolean isCallQueryMechanism() {
570         return false;
571     }
572
573     /**
574      * Return true if this is an expression query mechanism
575      */

576     public boolean isExpressionQueryMechanism() {
577         return false;
578     }
579
580     /**
581      * Return true if this is a query by example mechanism
582      */

583     public boolean isQueryByExampleMechanism() {
584         return false;
585     }
586
587     /**
588      * Return true if this is a statement query mechanism
589      */

590     public boolean isStatementQueryMechanism() {
591         return false;
592     }
593
594     /**
595      * Insert the object using the user defined query.
596      * This ensures that the query is cloned and prepared correctly.
597      */

598     protected void performUserDefinedInsert() {
599         performUserDefinedWrite(getDescriptor().getQueryManager().getInsertQuery());
600     }
601
602     /**
603      * Update the object using the user defined query.
604      * This ensures that the query is cloned and prepared correctly.
605      */

606     protected void performUserDefinedUpdate() {
607         performUserDefinedWrite(getDescriptor().getQueryManager().getUpdateQuery());
608     }
609
610     /**
611      * Write the object using the specified user-defined query.
612      * This ensures that the query is cloned and prepared correctly.
613      */

614     protected void performUserDefinedWrite(WriteObjectQuery userDefinedWriteQuery) {
615         userDefinedWriteQuery.checkPrepare(getSession(), getTranslationRow());
616
617         Object JavaDoc object = getWriteObjectQuery().getObject();
618         WriteObjectQuery writeQuery = (WriteObjectQuery)userDefinedWriteQuery.clone();
619         writeQuery.setObject(object);
620         writeQuery.setObjectChangeSet(getWriteObjectQuery().getObjectChangeSet());
621         writeQuery.setCascadePolicy(getQuery().getCascadePolicy());
622         writeQuery.setShouldMaintainCache(getQuery().shouldMaintainCache());
623         writeQuery.setTranslationRow(getTranslationRow());
624         writeQuery.setModifyRow(getModifyRow());
625         writeQuery.setPrimaryKey(getWriteObjectQuery().getPrimaryKey());
626         writeQuery.setSession(getSession());
627         writeQuery.prepareForExecution();
628
629         // HACK: If there is a changeset, the change set method must be used,
630
// however it is currently broken for inserts, so until this is fixed,
631
// only using correct commit for updates.
632
if (getWriteObjectQuery().isUpdateObjectQuery() && (getWriteObjectQuery().getObjectChangeSet() != null)) {
633             writeQuery.executeCommitWithChangeSet();
634         } else {
635             writeQuery.executeCommit();
636         }
637     }
638
639     /**
640      * This is different from 'prepareForExecution()'
641      * in that this is called on the original query,
642      * and the other is called on the clone of the query.
643      * This query is copied for concurrency so this prepare can only setup things that
644      * will apply to any future execution of this query.
645      */

646     public void prepare() throws QueryException {
647         // the default is to do nothing
648
}
649
650     /**
651      * Pre-pare for a cursored execute.
652      * This is sent to the original query before cloning.
653      */

654     public abstract void prepareCursorSelectAllRows() throws QueryException;
655
656     /**
657      * Prepare for a delete all.
658      * This is sent to the original query before cloning.
659      */

660     public abstract void prepareDeleteAll() throws QueryException;
661
662     /**
663      * Prepare for a delete.
664      * This is sent to the original query before cloning.
665      */

666     public abstract void prepareDeleteObject() throws QueryException;
667
668     /**
669      * Pre-pare for a select execute.
670      * This is sent to the original query before cloning.
671      */

672     public abstract void prepareDoesExist(DatabaseField field) throws QueryException;
673
674     /**
675      * Prepare for a raw (non-object), non-selecting call.
676      * This is sent to the original query before cloning.
677      */

678     public abstract void prepareExecuteNoSelect() throws QueryException;
679
680     /**
681      * Prepare for a raw (non-object) select call.
682      * This is sent to the original query before cloning.
683      */

684     public abstract void prepareExecuteSelect() throws QueryException;
685
686     /**
687      * All the query mechanism related things are initialized here.
688      * This method is called on the *clone* of the query with
689      * every execution.
690      */

691     public void prepareForExecution() throws QueryException {
692         // the default is to do nothing
693
}
694
695     /**
696      * Prepare for an insert.
697      * This is sent to the original query before cloning.
698      */

699     public abstract void prepareInsertObject() throws QueryException;
700
701     /**
702      * Pre-pare for a select execute.
703      * This is sent to the original query before cloning.
704      */

705     public abstract void prepareReportQuerySelectAllRows() throws QueryException;
706
707     /**
708      * Pre-pare a report query for a sub-select.
709      */

710     public abstract void prepareReportQuerySubSelect() throws QueryException;
711
712     /**
713      * Prepare for a select returning (possibly) multiple rows.
714      * This is sent to the original query before cloning.
715      */

716     public abstract void prepareSelectAllRows() throws QueryException;
717
718     /**
719      * Prepare for a select returning a single row.
720      * This is sent to the original query before cloning.
721      */

722     public abstract void prepareSelectOneRow() throws QueryException;
723
724     /**
725      * Prepare for an update.
726      * This is sent to the original query before cloning.
727      */

728     public abstract void prepareUpdateObject() throws QueryException;
729
730     /**
731        * Prepare for an update all.
732        * This is sent to the original query before cloning.
733        */

734     public abstract void prepareUpdateAll() throws QueryException;
735
736     /**
737      * Store the query object in the identity map.
738      */

739     protected void registerObjectInIdentityMap() {
740         WriteObjectQuery writeQuery = getWriteObjectQuery();
741         Object JavaDoc object = writeQuery.getObject();
742
743         if (writeQuery.shouldMaintainCache()) {
744             if (getDescriptor().usesOptimisticLocking()) {
745                 Object JavaDoc optimisticLockValue = getDescriptor().getOptimisticLockingPolicy().getValueToPutInCache(writeQuery.getModifyRow(), getSession());
746                 getSession().getIdentityMapAccessorInstance().putInIdentityMap(object, writeQuery.getPrimaryKey(), optimisticLockValue, System.currentTimeMillis(), getDescriptor());
747             } else {
748                 getSession().getIdentityMapAccessorInstance().putInIdentityMap(object, writeQuery.getPrimaryKey(), null, System.currentTimeMillis(), getDescriptor());
749             }
750         }
751     }
752
753     /**
754      * INTERNAL:
755      * Read all rows from the database.
756      */

757     public abstract Vector selectAllReportQueryRows() throws DatabaseException;
758
759     /**
760      * Read and return rows from the database.
761      */

762     public abstract Vector selectAllRows() throws DatabaseException;
763
764     /**
765      * Read and return a row from the database.
766      */

767     public abstract AbstractRecord selectOneRow() throws DatabaseException;
768
769     /**
770      * Read and return a row from the database for an existence check.
771      */

772     public abstract AbstractRecord selectRowForDoesExist(DatabaseField field) throws DatabaseException;
773
774     /**
775      * Set the query that uses this mechanism.
776      */

777     public void setQuery(DatabaseQuery query) {
778         this.query = query;
779     }
780
781     /**
782      * Shallow insert the specified object, if necessary.
783      */

784     protected void shallowInsertObjectForWrite(Object JavaDoc object, WriteObjectQuery writeQuery, CommitManager commitManager) throws DatabaseException, OptimisticLockException {
785         boolean doesExist;
786
787         if (getSession().isUnitOfWork()) {
788             UnitOfWorkImpl uow = (UnitOfWorkImpl)getSession();
789             doesExist = !uow.isCloneNewObject(object);
790             if (doesExist) {
791                 doesExist = uow.isObjectRegistered(object);
792             }
793         } else {
794             // clone and initialize the does exist query
795
DoesExistQuery existQuery = (DoesExistQuery)getDescriptor().getQueryManager().getDoesExistQuery().clone();
796             existQuery.setObject(object);
797             existQuery.setPrimaryKey(writeQuery.getPrimaryKey());
798             existQuery.setDescriptor(getDescriptor());
799             existQuery.setTranslationRow(getTranslationRow());
800
801             doesExist = ((Boolean JavaDoc)getSession().executeQuery(existQuery)).booleanValue();
802         }
803
804         if (!doesExist) {
805             // a shallow insert must be performed
806
writeQuery.dontCascadeParts();
807             insertObjectForWrite();
808             // mark this object as shallow committed so that the insert will do an update
809
commitManager.markShallowCommit(object);
810         }
811     }
812
813     /**
814      * Update the foreign key fields when resolving a bi-directonal reference in a UOW.
815      * This must always be dynamic as it is called within an insert query and is really part of the insert
816      * and does not fire update events or worry about locking.
817      */

818     protected void updateForeignKeyFieldAfterInsert() {
819         WriteObjectQuery writeQuery = getWriteObjectQuery();
820         Object JavaDoc object = writeQuery.getObject();
821
822         writeQuery.setPrimaryKey(getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, getSession()));
823         // reset the translation row because the insert has occurred and the id has
824
// been assigned to the object, but not the row
825
writeQuery.setTranslationRow(getDescriptor().getObjectBuilder().buildRowForTranslation(object, getSession()));
826
827         updateForeignKeyFieldAfterInsert(writeQuery);
828     }
829
830     /**
831        * Issue update SQL statement
832        */

833     public abstract Integer JavaDoc updateAll() throws DatabaseException;
834
835     /**
836      * Update an object.
837      * Return the row count.
838      */

839     public abstract Integer JavaDoc updateObject() throws DatabaseException;
840
841     /**
842      * Update the foreign key fields when resolving a bi-directonal reference in a UOW.
843      * This must always be dynamic as it is called within an insert query and is really part of the insert
844      * and does not fire update events or worry about locking.
845      */

846     protected abstract void updateForeignKeyFieldAfterInsert(WriteObjectQuery writeQuery);
847
848     protected void updateObjectAndRowWithReturnRow(Collection returnFields, boolean isFirstCallForInsert) {
849         WriteObjectQuery writeQuery = getWriteObjectQuery();
850         AbstractRecord outputRow = (AbstractRecord)writeQuery.getProperties().get("output");
851         if ((outputRow == null) || outputRow.isEmpty()) {
852             return;
853         }
854         AbstractRecord row = new DatabaseRecord();
855         for (Iterator iterator = returnFields.iterator(); iterator.hasNext();) {
856             DatabaseField field = (DatabaseField)iterator.next();
857             if (outputRow.containsKey(field)) {
858                 row.put(field, outputRow.get(field));
859             }
860         }
861         if (row.isEmpty()) {
862             return;
863         }
864
865         Object JavaDoc object = writeQuery.getObject();
866
867         getDescriptor().getObjectBuilder().assignReturnRow(object, getSession(), row);
868
869         Vector primaryKeys = null;
870         if (isFirstCallForInsert) {
871             AbstractRecord pkToModify = new DatabaseRecord();
872             List primaryKeyFields = getDescriptor().getPrimaryKeyFields();
873             for (int i = 0; i < primaryKeyFields.size(); i++) {
874                 DatabaseField field = (DatabaseField)primaryKeyFields.get(i);
875                 if (row.containsKey(field)) {
876                     pkToModify.put(field, row.get(field));
877                 }
878             }
879             if (!pkToModify.isEmpty()) {
880                 primaryKeys = getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, getSession());
881                 writeQuery.setPrimaryKey(primaryKeys);
882                 // Now I need to update the row
883
getModifyRow().putAll(pkToModify);
884                 getDescriptor().getObjectBuilder().addPrimaryKeyForNonDefaultTable(getModifyRow());
885             }
886         }
887
888         // update the changeSet if there is one
889
if (getSession().isUnitOfWork()) {
890             ObjectChangeSet objectChangeSet = writeQuery.getObjectChangeSet();
891             if ((objectChangeSet == null) && (((UnitOfWorkImpl)getSession()).getUnitOfWorkChangeSet() != null)) {
892                 objectChangeSet = (ObjectChangeSet)((UnitOfWorkImpl)getSession()).getUnitOfWorkChangeSet().getObjectChangeSetForClone(object);
893             }
894             if (objectChangeSet != null) {
895                 updateChangeSet(getDescriptor(), objectChangeSet, row, object);
896                 if (primaryKeys != null) {
897                     objectChangeSet.setCacheKey(new CacheKey(primaryKeys));
898                 }
899             }
900         }
901     }
902
903     /**
904      * Update the change set with all of the field values in the row.
905      * This handle writable and read-only mappings, direct and nested aggregates.
906      * It is used from ReturningPolicy and VersionLockingPolicy.
907      */

908     public void updateChangeSet(ClassDescriptor desc, ObjectChangeSet objectChangeSet, AbstractRecord row, Object JavaDoc object) {
909         HashSet handledMappings = new HashSet(row.size());
910         for (int i = 0; i < row.size(); i++) {
911             DatabaseField field = (DatabaseField)row.getFields().elementAt(i);
912             Object JavaDoc value = row.getValues().elementAt(i);
913             updateChangeSet(desc, objectChangeSet, field, object, handledMappings);
914         }
915     }
916
917     protected void updateChangeSet(ClassDescriptor desc, ObjectChangeSet objectChangeSet, DatabaseField field, Object JavaDoc object) {
918         updateChangeSet(desc, objectChangeSet, field, object, null);
919     }
920
921     protected void updateChangeSet(ClassDescriptor desc, ObjectChangeSet objectChangeSet, DatabaseField field, Object JavaDoc object, Collection handledMappings) {
922         DatabaseMapping mapping;
923         Vector mappingVector = desc.getObjectBuilder().getReadOnlyMappingsForField(field);
924         if (mappingVector != null) {
925             for (int j = 0; j < mappingVector.size(); j++) {
926                 mapping = (DatabaseMapping)mappingVector.elementAt(j);
927                 updateChangeSet(mapping, objectChangeSet, field, object, handledMappings);
928             }
929         }
930         mapping = desc.getObjectBuilder().getMappingForField(field);
931         if (mapping != null) {
932             updateChangeSet(mapping, objectChangeSet, field, object, handledMappings);
933         }
934     }
935
936     protected void updateChangeSet(DatabaseMapping mapping, ObjectChangeSet objectChangeSet, DatabaseField field, Object JavaDoc object, Collection handledMappings) {
937         if ((handledMappings != null) && handledMappings.contains(mapping)) {
938             return;
939         }
940         if (mapping.isAggregateObjectMapping()) {
941             Object JavaDoc aggregate = mapping.getAttributeValueFromObject(object);
942             AggregateChangeRecord record = (AggregateChangeRecord)objectChangeSet.getChangesForAttributeNamed(mapping.getAttributeName());
943             if (aggregate != null) {
944                 if (record == null) {
945                     record = new AggregateChangeRecord(objectChangeSet);
946                     record.setAttribute(mapping.getAttributeName());
947                     record.setMapping(mapping);
948                     objectChangeSet.addChange(record);
949                 }
950                 ObjectChangeSet aggregateChangeSet = (oracle.toplink.essentials.internal.sessions.ObjectChangeSet)record.getChangedObject();
951                 ClassDescriptor aggregateDescriptor = ((AggregateObjectMapping)mapping).getReferenceDescriptor();
952                 if (aggregateChangeSet == null) {
953                     aggregateChangeSet = aggregateDescriptor.getObjectBuilder().createObjectChangeSet(aggregate, (oracle.toplink.essentials.internal.sessions.UnitOfWorkChangeSet)((UnitOfWorkImpl)getSession()).getUnitOfWorkChangeSet(), getSession());
954                     record.setChangedObject(aggregateChangeSet);
955                 }
956                 updateChangeSet(aggregateDescriptor, aggregateChangeSet, field, aggregate, handledMappings);
957             } else {
958                 if (record != null) {
959                     record.setChangedObject(null);
960                 }
961             }
962         } else if (mapping.isDirectToFieldMapping()) {
963             Object JavaDoc attributeValue = mapping.getAttributeValueFromObject(object);
964             objectChangeSet.updateChangeRecordForAttribute(mapping, attributeValue);
965         } else {
966             getSession().log(SessionLog.FINEST, SessionLog.QUERY, "field_for_unsupported_mapping_returned", field, getDescriptor());
967         }
968     }
969
970     /**
971      * Update the object's primary key by fetching a new sequence number from the accessor.
972      */

973     protected void updateObjectAndRowWithSequenceNumber() throws DatabaseException {
974         WriteObjectQuery writeQuery = getWriteObjectQuery();
975         Object JavaDoc object = writeQuery.getObject();
976
977         Object JavaDoc sequenceValue = getDescriptor().getObjectBuilder().assignSequenceNumber(object, getSession());
978         if (sequenceValue == null) {
979             return;
980         }
981         Vector primaryKeys = getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, getSession());
982         writeQuery.setPrimaryKey(primaryKeys);
983         DatabaseField sequenceNumberField = getDescriptor().getSequenceNumberField();
984
985         // Now I need to update the row
986
getModifyRow().put(sequenceNumberField, sequenceValue);
987         getDescriptor().getObjectBuilder().addPrimaryKeyForNonDefaultTable(getModifyRow());
988         // update the changeSet if there is one
989
if (getSession().isUnitOfWork()) {
990             ObjectChangeSet objectChangeSet = writeQuery.getObjectChangeSet();
991             if ((objectChangeSet == null) && (((UnitOfWorkImpl)getSession()).getUnitOfWorkChangeSet() != null)) {
992                 objectChangeSet = (ObjectChangeSet)((UnitOfWorkImpl)getSession()).getUnitOfWorkChangeSet().getObjectChangeSetForClone(object);
993             }
994             if (objectChangeSet != null) {
995                 updateChangeSet(getDescriptor(), objectChangeSet, sequenceNumberField, object);
996                 objectChangeSet.setCacheKey(new CacheKey(primaryKeys));
997             }
998         }
999     }
1000
1001    /**
1002     * Update the object
1003     */

1004    public void updateObjectForWrite() {
1005        WriteObjectQuery writeQuery = getWriteObjectQuery();
1006        Object JavaDoc object = writeQuery.getObject();
1007        DescriptorQueryManager queryManager = getDescriptor().getQueryManager();
1008
1009        // check for user-defined query
1010
if ((!writeQuery.isUserDefined())// this is not a user-defined query
1011
&&queryManager.hasUpdateQuery()// there is a user-defined query
1012
&&isExpressionQueryMechanism()) {// this is not a hand-coded call (custom SQL etc.)
1013
performUserDefinedUpdate();
1014            return;
1015        }
1016
1017        // This must be done after the custom query check, otherwise it will be done twice.
1018
getSession().getCommitManager().markPreModifyCommitInProgress(object);
1019
1020        if (writeQuery.getObjectChangeSet() == null) {
1021            // PERF: Avoid events if no listeners.
1022
if (getDescriptor().getEventManager().hasAnyEventListeners()) {
1023                // only throw the events if there is no changeset otherwise the event will be thrown twice
1024
// once by the calculate changes code and here
1025
getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PreUpdateEvent, writeQuery));
1026            }
1027        }
1028
1029        // Verify if deep shallow modify is turned on
1030
if (writeQuery.shouldCascadeParts()) {
1031            queryManager.preUpdate(writeQuery);
1032        }
1033
1034        // The row must not be built until after preUpdate in case the object reference has changed.
1035
// For a user defined update in the uow to row must be built twice to check if any update is required.
1036
if ((writeQuery.isUserDefined() || writeQuery.isCallQuery()) && (!getSession().isUnitOfWork())) {
1037            writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRow(object, getSession()));
1038        } else {
1039            writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowForUpdate(writeQuery));
1040        }
1041
1042        if (!getModifyRow().isEmpty()) {
1043            // If user defined the entire row is required. Must not be built until change is known.
1044
if ((writeQuery.isUserDefined() || writeQuery.isCallQuery()) && getSession().isUnitOfWork()) {
1045                writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRow(object, getSession()));
1046            }
1047
1048            // Update the write lock field if required
1049
if (getDescriptor().usesOptimisticLocking()) {
1050                OptimisticLockingPolicy policy = getDescriptor().getOptimisticLockingPolicy();
1051                policy.addLockValuesToTranslationRow(writeQuery);
1052
1053                // update the row with newer lock value
1054
policy.updateRowAndObjectForUpdate(writeQuery, object);
1055            }
1056
1057            // PERF: Avoid events if no listeners.
1058
if (getDescriptor().getEventManager().hasAnyEventListeners()) {
1059                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToUpdateEvent, writeQuery);
1060                event.setRecord(getModifyRow());
1061                getDescriptor().getEventManager().executeEvent(event);
1062            }
1063
1064            int rowCount = updateObject().intValue();
1065
1066            if (rowCount < 1) {
1067                getSession().getEventManager().noRowsModified(writeQuery, object);
1068            }
1069            if (getDescriptor().usesOptimisticLocking()) {
1070                getDescriptor().getOptimisticLockingPolicy().validateUpdate(rowCount, object, writeQuery);
1071            }
1072        }
1073
1074        getSession().getCommitManager().markPostModifyCommitInProgress(object);
1075
1076        // Verify if deep shallow modify is turned on
1077
if (writeQuery.shouldCascadeParts()) {
1078            queryManager.postUpdate(writeQuery);
1079        }
1080
1081        // PERF: Avoid events if no listeners.
1082
if (getDescriptor().getEventManager().hasAnyEventListeners()) {
1083            getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostUpdateEvent, writeQuery));
1084        }
1085    }
1086
1087    /**
1088     * Update the object
1089     */

1090    public void updateObjectForWriteWithChangeSet() {
1091        WriteObjectQuery writeQuery = getWriteObjectQuery();
1092        Object JavaDoc object = writeQuery.getObject();
1093        DescriptorQueryManager queryManager = getDescriptor().getQueryManager();
1094
1095        // check for user-defined query
1096
if ((!writeQuery.isUserDefined())// this is not a user-defined query
1097
&&queryManager.hasUpdateQuery()// there is a user-defined query
1098
&&isExpressionQueryMechanism()) {// this is not a hand-coded call (custom SQL etc.)
1099
// THis must be done here because the userdefined updatedoes not use a changeset so it will noe be set otherwise
1100
getSession().getCommitManager().markPreModifyCommitInProgress(writeQuery.getObjectChangeSet());
1101            performUserDefinedUpdate();
1102            return;
1103        }
1104
1105        // This must be done after the custom query check, otherwise it will be done twice.
1106
getSession().getCommitManager().markPreModifyCommitInProgress(object);
1107        // This must be done after the custom query check, otherwise it will be done twice.
1108
getSession().getCommitManager().markPreModifyCommitInProgress(writeQuery.getObjectChangeSet());
1109
1110        if (writeQuery.getObjectChangeSet().hasChanges()) {
1111            // PERF: Avoid events if no listeners.
1112
if (getDescriptor().getEventManager().hasAnyEventListeners()) {
1113                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.PreUpdateWithChangesEvent, writeQuery);
1114                getDescriptor().getEventManager().executeEvent(event);
1115
1116                // PreUpdateWithChangesEvent listeners may have altered the object - should recalculate the change set.
1117
UnitOfWorkChangeSet uowChangeSet = (oracle.toplink.essentials.internal.sessions.UnitOfWorkChangeSet)((UnitOfWorkImpl)writeQuery.getSession()).getUnitOfWorkChangeSet();
1118                // writeQuery.getObjectChangeSet() is mapped to object in uowChangeSet.
1119
// It is first cleared then re-populated by calculateChanges method.
1120
writeQuery.getObjectChangeSet().clear();
1121                if(writeQuery.getDescriptor().getObjectChangePolicy().calculateChanges(object, ((UnitOfWorkImpl)event.getSession()).getBackupClone(object), uowChangeSet, writeQuery.getSession(), writeQuery.getDescriptor(), false) == null) {
1122                    // calculateChanges returns null in case the changeSet doesn't have changes.
1123
// It should be removed from the list of ObjectChangeSets that have changes in uowChangeSet.
1124
uowChangeSet.getAllChangeSets().remove(writeQuery.getObjectChangeSet());
1125                }
1126            }
1127        }
1128         
1129        // Verify if deep shallow modify is turned on
1130
if (writeQuery.shouldCascadeParts()) {
1131            queryManager.preUpdate(writeQuery);
1132        }
1133
1134        // The row must not be built until after preUpdate in case the object reference has changed.
1135
// For a user defined update in the uow to row must be built twice to check if any update is required.
1136
writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowForUpdateWithChangeSet(writeQuery));
1137            
1138        Boolean JavaDoc shouldModifyVersionField = writeQuery.getObjectChangeSet().shouldModifyVersionField();
1139
1140        if (!getModifyRow().isEmpty() || (shouldModifyVersionField != null) || writeQuery.getObjectChangeSet().hasCmpPolicyForcedUpdate()) {
1141            // If user defined the entire row is required. Must not be built until change is known.
1142
if (writeQuery.isUserDefined() || writeQuery.isCallQuery()) {
1143                writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRow(object, getSession()));
1144            }
1145
1146            // Update the write lock field if required
1147
if (getDescriptor().usesOptimisticLocking()) {
1148                OptimisticLockingPolicy policy = getDescriptor().getOptimisticLockingPolicy();
1149                policy.addLockValuesToTranslationRow(writeQuery);
1150
1151                if (!getModifyRow().isEmpty() || (shouldModifyVersionField.booleanValue() && policy instanceof VersionLockingPolicy)) {
1152                    // update the row with newer lock value
1153
policy.updateRowAndObjectForUpdate(writeQuery, object);
1154                } else if (!shouldModifyVersionField.booleanValue() && policy instanceof VersionLockingPolicy) {
1155                    ((VersionLockingPolicy)policy).writeLockValueIntoRow(writeQuery, object);
1156                }
1157            }
1158
1159            // PERF: Avoid events if no listeners.
1160
if (getDescriptor().getEventManager().hasAnyEventListeners()) {
1161                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToUpdateEvent, writeQuery);
1162                event.setRecord(getModifyRow());
1163                getDescriptor().getEventManager().executeEvent(event);
1164            }
1165
1166            int rowCount = updateObject().intValue();
1167
1168            if (rowCount < 1) {
1169                getSession().getEventManager().noRowsModified(writeQuery, object);
1170            }
1171            if (getDescriptor().usesOptimisticLocking()) {
1172                getDescriptor().getOptimisticLockingPolicy().validateUpdate(rowCount, object, writeQuery);
1173            }
1174        }
1175
1176        getSession().getCommitManager().markPostModifyCommitInProgress(object);
1177        getSession().getCommitManager().markPostModifyCommitInProgress(writeQuery.getObjectChangeSet());
1178
1179        // Verify if deep shallow modify is turned on
1180
if (writeQuery.shouldCascadeParts()) {
1181            queryManager.postUpdate(writeQuery);
1182        }
1183
1184        // PERF: Avoid events if no listeners.
1185
if (getDescriptor().getEventManager().hasAnyEventListeners()) {
1186            getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostUpdateEvent, writeQuery));
1187        }
1188    }
1189}
1190
Popular Tags