/** * delete all of the objects as a single transaction. This should delete the object in the correct * order to maintain referential integrity. */ public void deleteAllObjects(List objects) throws RuntimeException, DatabaseException, OptimisticLockException { this.isActive = true; AbstractSession session = getSession(); session.beginTransaction(); try { // PERF: Optimize single object case. if (objects.size() == 1) { deleteAllObjects(objects.get(0).getClass(), objects, session); } else { List commitOrder = getCommitOrder(); for (int orderIndex = commitOrder.size() - 1; orderIndex >= 0; orderIndex--) { Class theClass = (Class) commitOrder.get(orderIndex); deleteAllObjects(theClass, objects, session); } } session.commitTransaction(); } catch (RuntimeException exception) { try { session.rollbackTransaction(); } catch (Exception ignore) { } throw exception; } finally { reinitialize(); this.isActive = false; } }
/** Delete all of the objects with the matching class. */ public void deleteAllObjects(Class theClass, List objects, AbstractSession session) { ClassDescriptor descriptor = null; if (((UnitOfWorkImpl) session).shouldOrderUpdates()) { // bug 331064 - Sort the delete order objects = sort(theClass, objects); } int size = objects.size(); for (int index = 0; index < size; index++) { Object objectToDelete = objects.get(index); if (objectToDelete.getClass() == theClass) { if (descriptor == null) { descriptor = session.getDescriptor(theClass); } // PERF: Get the descriptor query, to avoid extra query creation. DeleteObjectQuery deleteQuery = descriptor.getQueryManager().getDeleteQuery(); if (deleteQuery == null) { deleteQuery = new DeleteObjectQuery(); deleteQuery.setDescriptor(descriptor); } else { // Ensure original query has been prepared. deleteQuery.checkPrepare(session, deleteQuery.getTranslationRow()); deleteQuery = (DeleteObjectQuery) deleteQuery.clone(); } deleteQuery.setIsExecutionClone(true); deleteQuery.setObject(objectToDelete); session.executeQuery(deleteQuery); } } }
/** * Commit all of the objects of the class type in the change set. This allows for the order of the * classes to be processed optimally. */ protected void commitNewObjectsForClassWithChangeSet( UnitOfWorkChangeSet uowChangeSet, Class theClass) { Map<ObjectChangeSet, ObjectChangeSet> newObjectChangesList = uowChangeSet.getNewObjectChangeSets().get(theClass); if (newObjectChangesList != null) { // may be no changes for that class type. AbstractSession session = getSession(); ClassDescriptor descriptor = session.getDescriptor(theClass); List<ObjectChangeSet> newChangeSets = new ArrayList(newObjectChangesList.values()); int size = newChangeSets.size(); for (int index = 0; index < size; index++) { ObjectChangeSet changeSetToWrite = newChangeSets.get(index); Object objectToWrite = changeSetToWrite.getUnitOfWorkClone(); if (!isProcessedCommit(objectToWrite)) { // PERF: Get the descriptor query, to avoid extra query creation. InsertObjectQuery commitQuery = descriptor.getQueryManager().getInsertQuery(); if (commitQuery == null) { commitQuery = new InsertObjectQuery(); commitQuery.setDescriptor(descriptor); } else { // Ensure original query has been prepared. commitQuery.checkPrepare(session, commitQuery.getTranslationRow()); commitQuery = (InsertObjectQuery) commitQuery.clone(); } commitQuery.setIsExecutionClone(true); commitQuery.setObjectChangeSet(changeSetToWrite); commitQuery.setObject(objectToWrite); commitQuery.cascadeOnlyDependentParts(); commitQuery.setModifyRow(null); session.executeQuery(commitQuery); } uowChangeSet.putNewObjectInChangesList(changeSetToWrite, session); } } }
// bug 331064 - Sort the delete order based on PKs. private List sort(Class theClass, List objects) { ClassDescriptor descriptor = session.getDescriptor(theClass); org.eclipse.persistence.internal.descriptors.ObjectBuilder objectBuilder = descriptor.getObjectBuilder(); int size = objects.size(); TreeMap sortedObjects = new TreeMap(); for (int index = 0; index < size; index++) { Object objectToDelete = objects.get(index); if (objectToDelete.getClass() == theClass) { sortedObjects.put( objectBuilder.extractPrimaryKeyFromObject(objectToDelete, session), objectToDelete); } } return new ArrayList(sortedObjects.values()); }
/** * Commit all of the objects as a single transaction. This should commit the object in the correct * order to maintain referential integrity. */ public void commitAllObjectsWithChangeSet(UnitOfWorkChangeSet uowChangeSet) throws RuntimeException, DatabaseException, OptimisticLockException { reinitialize(); this.isActive = true; this.session.beginTransaction(); try { // PERF: if the number of classes in the project is large this loop can be a perf issue. // If only one class types changed, then avoid loop. if ((uowChangeSet.getObjectChanges().size() + uowChangeSet.getNewObjectChangeSets().size()) <= 1) { Iterator<Class> classes = uowChangeSet.getNewObjectChangeSets().keySet().iterator(); if (classes.hasNext()) { Class theClass = classes.next(); commitNewObjectsForClassWithChangeSet(uowChangeSet, theClass); } classes = uowChangeSet.getObjectChanges().keySet().iterator(); if (classes.hasNext()) { Class theClass = classes.next(); commitChangedObjectsForClassWithChangeSet(uowChangeSet, theClass); } } else { // The commit order is all of the classes ordered by dependencies, this is done for deadlock // avoidance. List commitOrder = getCommitOrder(); int size = commitOrder.size(); for (int index = 0; index < size; index++) { Class theClass = (Class) commitOrder.get(index); commitAllObjectsForClassWithChangeSet(uowChangeSet, theClass); } } if (hasDeferredCalls()) { // Perform all batched up calls, done to avoid dependencies. for (List<Object[]> calls : this.deferredCalls.values()) { for (Object[] argument : calls) { ((DatabaseQueryMechanism) argument[1]) .executeDeferredCall((DatasourceCall) argument[0]); } } } if (hasDataModifications()) { // Perform all batched up data modifications, done to avoid dependencies. for (Map.Entry<DatabaseMapping, List<Object[]>> entry : this.dataModifications.entrySet()) { List<Object[]> events = entry.getValue(); int size = events.size(); DatabaseMapping mapping = entry.getKey(); for (int index = 0; index < size; index++) { Object[] event = events.get(index); mapping.performDataModificationEvent(event, getSession()); } } } if (hasObjectsToDelete()) { // These are orphaned objects, to be deleted from private ownership updates. // TODO: These should be added to the unit of work deleted so they are deleted in the // correct order. List objects = getObjectsToDelete(); int size = objects.size(); reinitialize(); for (int index = 0; index < size; index++) { this.session.deleteObject(objects.get(index)); } } this.session.commitTransaction(); } catch (RuntimeException exception) { this.session.rollbackTransaction(); throw exception; } finally { reinitialize(); this.isActive = false; } }