1 21 package oracle.toplink.essentials.internal.ejb.cmp3.base; 23 24 import java.util.Enumeration ; 25 26 import oracle.toplink.essentials.descriptors.ClassDescriptor; 27 import oracle.toplink.essentials.internal.descriptors.DescriptorIterator; 28 import oracle.toplink.essentials.internal.helper.IdentityHashtable; 29 import oracle.toplink.essentials.internal.localization.ExceptionLocalization; 30 import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl; 31 import oracle.toplink.essentials.exceptions.DatabaseException; 32 import oracle.toplink.essentials.exceptions.OptimisticLockException; 33 import oracle.toplink.essentials.internal.sessions.UnitOfWorkChangeSet; 34 import oracle.toplink.essentials.internal.sessions.ObjectChangeSet; 35 import oracle.toplink.essentials.mappings.ForeignReferenceMapping; 36 37 38 public class RepeatableWriteUnitOfWork extends UnitOfWorkImpl { 39 40 41 protected UnitOfWorkChangeSet cumulativeUOWChangeSet; 42 43 protected IdentityHashtable unregisteredDeletedObjectsCloneToBackupAndOriginal; 44 45 48 protected boolean shouldTerminateTransaction; 49 50 public RepeatableWriteUnitOfWork(oracle.toplink.essentials.internal.sessions.AbstractSession parentSession){ 51 super(parentSession); 52 this.shouldTerminateTransaction = true; 53 } 54 55 59 public void clear(){ 60 this.getIdentityMapAccessor().initializeIdentityMaps(); 61 this.cloneToOriginals = null; 62 this.cloneMapping = new IdentityHashtable();; 63 this.newObjectsCloneToOriginal = null; 64 this.newObjectsOriginalToClone = null; 65 this.deletedObjects = null; 66 this.allClones = null; 67 this.objectsDeletedDuringCommit = null; 68 this.removedObjects = null; 69 this.unregisteredNewObjects = null; 70 this.unregisteredExistingObjects = null; 71 this.newAggregates = null; 72 this.unitOfWorkChangeSet = null; 73 this.pessimisticLockedObjects = null; 74 this.optimisticReadLockObjects = null; 75 } 76 77 81 public void commitRootUnitOfWork() throws DatabaseException, OptimisticLockException { 82 commitToDatabaseWithChangeSet(false); 83 if(this.cumulativeUOWChangeSet != null) { 85 this.cumulativeUOWChangeSet.mergeUnitOfWorkChangeSet((UnitOfWorkChangeSet)this.getUnitOfWorkChangeSet(), this, true); 86 setUnitOfWorkChangeSet(this.cumulativeUOWChangeSet); 87 } 88 89 commitTransactionAfterWriteChanges(); 92 mergeChangesIntoParent(); 94 } 95 96 100 public void discoverUnregisteredNewObjects(Object clone, IdentityHashtable knownNewObjects, IdentityHashtable unregisteredExistingObjects, IdentityHashtable visitedObjects) { 101 DescriptorIterator iterator = new DescriptorIterator() { 103 public void iterate(Object object) { 104 if (isClassReadOnly(object.getClass()) || isObjectDeleted(object)) { 106 this.setShouldBreak(true); 107 return; 108 } 109 if ((getCurrentMapping() != null) && ((ForeignReferenceMapping)getCurrentMapping()).isCascadePersist() ){ 111 ((RepeatableWriteUnitOfWork)getSession()).registerNewObjectForPersist(object, new IdentityHashtable()); 112 }else{ 113 if (!getCloneMapping().containsKey(object)){ 114 if (! checkForUnregisteredExistingObject(object)){ 115 throw new IllegalStateException (ExceptionLocalization.buildMessage("new_object_found_during_commit", new Object []{object})); 116 }else{ 117 ((IdentityHashtable)getUnregisteredExistingObjects()).put(object, object); 118 this.setShouldBreak(true); 119 return; 120 } 121 } 122 } 123 } 124 }; 125 126 setUnregisteredExistingObjects(unregisteredExistingObjects); 128 129 iterator.setVisitedObjects(visitedObjects); 130 iterator.setResult(knownNewObjects); 131 iterator.setSession(this); 132 iterator.setShouldIterateOverWrappedObjects(false); 136 iterator.startIterationOn(clone); 137 } 138 139 145 public boolean isAfterWriteChangesButBeforeCommit() { 146 return (getLifecycle() == CommitTransactionPending); 148 } 149 150 154 public boolean isObjectDeleted(Object object) { 155 if(super.isObjectDeleted(object)) { 156 return true; 157 } else { 158 if(unregisteredDeletedObjectsCloneToBackupAndOriginal != null) { 159 if(unregisteredDeletedObjectsCloneToBackupAndOriginal.containsKey(object)) { 160 return true; 161 } 162 } 163 if (hasObjectsDeletedDuringCommit()) { 164 return getObjectsDeletedDuringCommit().containsKey(object); 165 } else { 166 return false; 167 } 168 } 169 } 170 171 175 public void issueSQLbeforeCompletion() { 176 177 super.issueSQLbeforeCompletion(false); 178 179 if (this.cumulativeUOWChangeSet != null && this.getUnitOfWorkChangeSet() != null){ 180 this.cumulativeUOWChangeSet.mergeUnitOfWorkChangeSet((UnitOfWorkChangeSet)this.getUnitOfWorkChangeSet(), this, true); 182 setUnitOfWorkChangeSet(this.cumulativeUOWChangeSet); 183 } 184 185 commitTransactionAfterWriteChanges(); } 188 189 193 public void updateChangeTrackersIfRequired(Object objectToWrite, ObjectChangeSet changeSetToWrite, UnitOfWorkImpl uow, ClassDescriptor descriptor) { 194 descriptor.getObjectChangePolicy().updateWithChanges(objectToWrite, changeSetToWrite, uow, descriptor); 195 } 196 197 203 public void writeChanges() { 204 if(unregisteredDeletedObjectsCloneToBackupAndOriginal == null) { 205 unregisteredDeletedObjectsCloneToBackupAndOriginal = new IdentityHashtable(2); 206 } 207 IdentityHashtable allObjectsList = new IdentityHashtable(); 208 IdentityHashtable visitedNodes = new IdentityHashtable(2); 209 IdentityHashtable newObjects = new IdentityHashtable(2); 210 IdentityHashtable existingObjects = new IdentityHashtable(2); 211 IdentityHashtable insertedNewObjects = new IdentityHashtable(2); 212 for (Enumeration clones = getCloneMapping().keys(); clones.hasMoreElements();){ 213 Object object = clones.nextElement(); 214 discoverUnregisteredNewObjects(object, newObjects, existingObjects, visitedNodes); 215 allObjectsList.put(object, object); 216 } 217 for (Enumeration newClones = getNewObjectsCloneToOriginal().keys();newClones.hasMoreElements();){ 218 Object object = newClones.nextElement(); 219 assignSequenceNumber(object); 220 insertedNewObjects.put(object, object); 221 allObjectsList.put(object, object); 223 } 224 225 if (getUnitOfWorkChangeSet() == null) { 226 setUnitOfWorkChangeSet(new UnitOfWorkChangeSet()); 227 } 228 calculateChanges(allObjectsList, (UnitOfWorkChangeSet)getUnitOfWorkChangeSet()); 229 UnitOfWorkChangeSet changeSet = (UnitOfWorkChangeSet)getUnitOfWorkChangeSet(); 231 if (!changeSet.hasChanges() && !changeSet.hasForcedChanges() && ! this.hasDeletedObjects() && ! this.hasModifyAllQueries()){ 232 return; 233 } 234 try { 235 commitToDatabaseWithPreBuiltChangeSet(changeSet, false); 236 this.writesCompleted(); 237 } catch (RuntimeException ex) { 238 setLifecycle(WriteChangesFailed); 239 throw ex; 240 } 241 getDeletedObjects().clear(); 243 244 Enumeration enumDeleted = getObjectsDeletedDuringCommit().keys(); 247 while(enumDeleted.hasMoreElements()) { 248 Object deletedObject = enumDeleted.nextElement(); 249 Object [] backupAndOriginal = {getCloneMapping().get(deletedObject), getCloneToOriginals().get(deletedObject)}; 250 unregisteredDeletedObjectsCloneToBackupAndOriginal.put(deletedObject, backupAndOriginal); 251 unregisterObject(deletedObject); 252 } 253 getObjectsDeletedDuringCommit().clear(); 254 255 if(this.cumulativeUOWChangeSet == null) { 256 this.cumulativeUOWChangeSet = (UnitOfWorkChangeSet)getUnitOfWorkChangeSet(); 257 } else { 258 this.cumulativeUOWChangeSet.mergeUnitOfWorkChangeSet((UnitOfWorkChangeSet)getUnitOfWorkChangeSet(), this, true); 260 } 261 setUnitOfWorkChangeSet(new UnitOfWorkChangeSet()); 263 Enumeration enumtr = insertedNewObjects.elements(); 264 while (enumtr.hasMoreElements()) { 265 Object clone = enumtr.nextElement(); 266 Object original = getNewObjectsCloneToOriginal().remove(clone); 267 if (original != null) { 268 getNewObjectsOriginalToClone().remove(original); 269 getCloneToOriginals().put(clone, original); 271 } 272 } 273 } 274 275 283 protected void registerNotRegisteredNewObjectForPersist(Object newObject, ClassDescriptor descriptor) { 284 if(unregisteredDeletedObjectsCloneToBackupAndOriginal != null) { 285 Object [] backupAndOriginal = (Object [])unregisteredDeletedObjectsCloneToBackupAndOriginal.remove(newObject); 286 if(backupAndOriginal != null) { 287 getCloneMapping().put(newObject, backupAndOriginal[0]); 289 registerNewObjectClone(newObject, backupAndOriginal[1]); 291 292 registerNewObjectInIdentityMap(newObject, newObject); 294 295 return; 296 } 297 } 298 super.registerNotRegisteredNewObjectForPersist(newObject, descriptor); 299 } 300 301 306 public void rollbackTransaction() throws DatabaseException { 307 if (this.shouldTerminateTransaction || getParent().getTransactionMutex().isNested()){ 308 super.rollbackTransaction(); 309 }else{ 310 setWasTransactionBegunPrematurely(true); 315 } 316 } 317 318 323 public void synchronizeAndResume() { 324 this.cumulativeUOWChangeSet = null; 325 super.synchronizeAndResume(); 326 } 327 328 333 public Object getUnregisteredDeletedCloneForOriginal(Object original) { 334 if(unregisteredDeletedObjectsCloneToBackupAndOriginal != null) { 335 Enumeration keys = unregisteredDeletedObjectsCloneToBackupAndOriginal.keys(); 336 Enumeration values = unregisteredDeletedObjectsCloneToBackupAndOriginal.elements(); 337 while(keys.hasMoreElements()) { 338 Object deletedObjectClone = keys.nextElement(); 339 Object [] backupAndOriginal = (Object [])values.nextElement(); 340 Object currentOriginal = backupAndOriginal[1]; 341 if(original == currentOriginal) { 342 return deletedObjectClone; 343 } 344 } 345 } 346 return null; 347 } 348 349 355 protected void commitToDatabase(boolean commitTransaction) { 356 try { 357 super.commitToDatabase(commitTransaction); 358 } catch (oracle.toplink.essentials.exceptions.OptimisticLockException ole) { 359 throw new javax.persistence.OptimisticLockException(ole); 360 } 361 } 362 363 368 public void commitTransaction() throws DatabaseException { 369 if (this.shouldTerminateTransaction || getParent().getTransactionMutex().isNested()){ 370 super.commitTransaction(); 371 } 372 } 373 374 public void setShouldTerminateTransaction(boolean shouldTerminateTransaction) { 375 this.shouldTerminateTransaction = shouldTerminateTransaction; 376 } 377 } 378 | Popular Tags |