/** INTERNAL: Begin the transaction on all child sessions. */ protected void basicBeginTransaction() throws DatabaseException { for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) { AbstractSession session = (AbstractSession) sessionEnum.next(); session.beginTransaction(); } }
/** * Return the next sequence value. First check the global pool, if empty then allocate new * sequences locally. */ public Object getNextValue(Sequence sequence, AbstractSession writeSession) { String seqName = sequence.getName(); if (sequence.getPreallocationSize() > 1) { Queue sequencesForName = getPreallocationHandler().getPreallocated(seqName); // First grab the first sequence value without locking, a lock is only required if empty. Object sequenceValue = sequencesForName.poll(); if (sequenceValue != null) { return sequenceValue; } // KeepLocked indicates whether the sequence lock should be kept for the whole duration of // this method. // Of course the lock should be released in any case when the method returns or throws an // exception. // This is only used if a sequence transaction was begun by the unit of work, // and will be committed before the unit of work commit. boolean keepLocked = false; if (!getOwnerSession().getDatasourceLogin().shouldUseExternalTransactionController() && !writeSession.isInTransaction()) { // To prevent several threads from simultaneously allocating a separate bunch of // sequencing numbers each. With keepLocked==true the first thread locks out others // until it copies the obtained sequence numbers to the global storage. // Note that this optimization possible only in non-jts case when there is no transaction. acquireLock(seqName); try { sequenceValue = sequencesForName.poll(); if (sequenceValue != null) { return sequenceValue; } writeSession.beginTransaction(); // write accessor is set in begin keepLocked = true; } finally { if (!keepLocked) { releaseLock(seqName); } } } Accessor accessor; Vector localSequencesForName; if (!keepLocked) { writeSession.beginTransaction(); // write accessor is set in begin } try { accessor = writeSession.getAccessor(); SequencingCallbackImpl seqCallbackImpl = getCallbackImpl(writeSession, accessor); Map localSequences = seqCallbackImpl.getPreallocatedSequenceValues(); localSequencesForName = (Vector) localSequences.get(seqName); if ((localSequencesForName == null) || localSequencesForName.isEmpty()) { localSequencesForName = sequence.getGeneratedVector(null, writeSession); localSequences.put(seqName, localSequencesForName); logDebugLocalPreallocation(writeSession, seqName, localSequencesForName, accessor); } } catch (RuntimeException ex) { if (keepLocked) { releaseLock(seqName); } try { // make sure to rollback the transaction we've begun writeSession.rollbackTransaction(); } catch (Exception rollbackException) { // ignore rollback exception } // don't eat the original exception throw ex; } try { try { // commitTransaction may copy preallocated sequence numbers // from localSequences to preallocationHandler: that happens // if it isn't a nested transaction, and sequencingCallback.afterCommit // method has been called. // In this case: // 1. localSequences corresponding to the accessor // has been removed from accessorToPreallocated; // 2. All its members are empty (therefore localSequenceForName is empty). writeSession.commitTransaction(); } catch (DatabaseException ex) { try { // make sure to rollback the transaction we've begun writeSession.rollbackTransaction(); } catch (Exception rollbackException) { // ignore rollback exception } // don't eat the original exception throw ex; } if (!localSequencesForName.isEmpty()) { // localSeqencesForName is not empty, that means // sequencingCallback has not been called. sequenceValue = localSequencesForName.remove(0); return sequenceValue; } else { // localSeqencesForName is empty, that means // sequencingCallback has been called. sequenceValue = sequencesForName.poll(); if (sequenceValue != null) { return sequenceValue; } return getNextValue(sequence, writeSession); } } finally { if (keepLocked) { releaseLock(seqName); } } } else { writeSession.beginTransaction(); try { // preallocation size is 1 - just return the first (and only) element of the allocated // vector. Object sequenceValue = sequence.getGeneratedVector(null, writeSession).firstElement(); writeSession.commitTransaction(); return sequenceValue; } catch (RuntimeException ex) { try { // make sure to rollback the transaction we've begun writeSession.rollbackTransaction(); } catch (Exception rollbackException) { // ignore rollback exception } // don't eat the original exception throw ex; } } }
/** * INTERNAL: Perform the work to delete an object. * * @return object - the object being deleted. */ public Object executeDatabaseQuery() throws DatabaseException, OptimisticLockException { AbstractSession session = getSession(); CommitManager commitManager = session.getCommitManager(); Object object = getObject(); boolean isUnitOfWork = session.isUnitOfWork(); try { // Check if the object has already been committed, then no work is required if (commitManager.isProcessedCommit(object)) { return object; } commitManager.markPreModifyCommitInProgress(getObject()); if (!isUnitOfWork) { session.beginTransaction(); } ClassDescriptor descriptor = this.descriptor; DescriptorEventManager eventManager = descriptor.getEventManager(); // PERF: Avoid events if no listeners. if (eventManager.hasAnyEventListeners()) { // Need to run pre-delete selector if available eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PreDeleteEvent, this)); } // Verify if deep shallow modify is turned on if (shouldCascadeParts()) { descriptor.getQueryManager().preDelete(this); } // CR#2660080 missing aboutToDelete event. // PERF: Avoid events if no listeners. if (eventManager.hasAnyEventListeners()) { DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToDeleteEvent, this); event.setRecord(getModifyRow()); eventManager.executeEvent(event); } if (QueryMonitor.shouldMonitor()) { QueryMonitor.incrementDelete(this); } int rowCount = 0; // If the object was/will be deleted from a cascade delete constraint, ignore it. if (isUnitOfWork && ((UnitOfWorkImpl) session).hasCascadeDeleteObjects() && ((UnitOfWorkImpl) session).getCascadeDeleteObjects().contains(object)) { // Cascade delete does not check optimistic lock, assume ok. rowCount = 1; } else { rowCount = getQueryMechanism().deleteObject().intValue(); } if (rowCount < 1) { if (session.hasEventManager()) { session.getEventManager().noRowsModified(this, object); } } if (descriptor.usesOptimisticLocking()) { descriptor.getOptimisticLockingPolicy().validateDelete(rowCount, object, this); } commitManager.markPostModifyCommitInProgress(getObject()); // Verify if deep shallow modify is turned on if (shouldCascadeParts()) { descriptor.getQueryManager().postDelete(this); } if ((descriptor.getHistoryPolicy() != null) && descriptor.getHistoryPolicy().shouldHandleWrites()) { descriptor.getHistoryPolicy().postDelete(this); } // PERF: Avoid events if no listeners. if (eventManager.hasAnyEventListeners()) { // Need to run post-delete selector if available eventManager.executeEvent( new DescriptorEvent(DescriptorEventManager.PostDeleteEvent, this)); } if (!isUnitOfWork) { session.commitTransaction(); } commitManager.markCommitCompleted(object); // CR3510313, avoid removing aggregate collections from cache (maintain cache is false). if (shouldMaintainCache()) { if (isUnitOfWork) { ((UnitOfWorkImpl) session).addObjectDeletedDuringCommit(object, descriptor); } else { session .getIdentityMapAccessorInstance() .removeFromIdentityMap( getPrimaryKey(), descriptor.getJavaClass(), descriptor, object); } } return object; } catch (RuntimeException exception) { if (!isUnitOfWork) { session.rollbackTransaction(); } commitManager.markCommitCompleted(object); throw exception; } }
/** * INTERNAL: Perform the work to delete an object. * * @return object - the object being deleted. */ public Object executeDatabaseQuery() throws DatabaseException, OptimisticLockException { AbstractSession session = getSession(); CommitManager commitManager = session.getCommitManager(); Object object = getObject(); boolean isUnitOfWork = session.isUnitOfWork(); try { // Check if the object has already been deleted, then no work is required. if (commitManager.isCommitCompletedInPostOrIgnore(object)) { return object; } ClassDescriptor descriptor = this.descriptor; // Check whether the object is already being deleted, // if it is, then there is a cycle, and the foreign keys must be nulled. if (commitManager.isCommitInPreModify(object)) { if (!commitManager.isShallowCommitted(object)) { getQueryMechanism().updateForeignKeyFieldBeforeDelete(); if ((descriptor.getHistoryPolicy() != null) && descriptor.getHistoryPolicy().shouldHandleWrites()) { descriptor.getHistoryPolicy().postUpdate(this); } commitManager.markShallowCommit(object); } return object; } commitManager.markPreModifyCommitInProgress(getObject()); if (!isUnitOfWork) { session.beginTransaction(); } DescriptorEventManager eventManager = descriptor.getEventManager(); // PERF: Avoid events if no listeners. if (eventManager.hasAnyEventListeners()) { // Need to run pre-delete selector if available eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PreDeleteEvent, this)); } // Verify if deep shallow modify is turned on if (shouldCascadeParts()) { descriptor.getQueryManager().preDelete(this); } // Check for deletion dependencies. if (isUnitOfWork) { Set dependencies = ((UnitOfWorkImpl) session).getDeletionDependencies(object); if (dependencies != null) { for (Object dependency : dependencies) { if (!commitManager.isCommitCompletedInPostOrIgnore(dependency)) { ClassDescriptor dependencyDescriptor = session.getDescriptor(dependency); // PERF: Get the descriptor query, to avoid extra query creation. DeleteObjectQuery deleteQuery = dependencyDescriptor.getQueryManager().getDeleteQuery(); if (deleteQuery == null) { deleteQuery = new DeleteObjectQuery(); deleteQuery.setDescriptor(dependencyDescriptor); } else { // Ensure original query has been prepared. deleteQuery.checkPrepare(session, deleteQuery.getTranslationRow()); deleteQuery = (DeleteObjectQuery) deleteQuery.clone(); } deleteQuery.setIsExecutionClone(true); deleteQuery.setObject(dependency); session.executeQuery(deleteQuery); } } } } // CR#2660080 missing aboutToDelete event. // PERF: Avoid events if no listeners. if (eventManager.hasAnyEventListeners()) { DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToDeleteEvent, this); event.setRecord(getModifyRow()); eventManager.executeEvent(event); } if (QueryMonitor.shouldMonitor()) { QueryMonitor.incrementDelete(this); } int rowCount = 0; // If the object was/will be deleted from a cascade delete constraint, ignore it. if (isUnitOfWork && ((UnitOfWorkImpl) session).hasCascadeDeleteObjects() && ((UnitOfWorkImpl) session).getCascadeDeleteObjects().contains(object)) { // Cascade delete does not check optimistic lock, assume ok. rowCount = 1; } else { rowCount = getQueryMechanism().deleteObject().intValue(); } if (rowCount < 1) { if (session.hasEventManager()) { session.getEventManager().noRowsModified(this, object); } } if (this.usesOptimisticLocking) { descriptor.getOptimisticLockingPolicy().validateDelete(rowCount, object, this); } commitManager.markPostModifyCommitInProgress(getObject()); // Verify if deep shallow modify is turned on if (shouldCascadeParts()) { descriptor.getQueryManager().postDelete(this); } if ((descriptor.getHistoryPolicy() != null) && descriptor.getHistoryPolicy().shouldHandleWrites()) { descriptor.getHistoryPolicy().postDelete(this); } // PERF: Avoid events if no listeners. if (eventManager.hasAnyEventListeners()) { // Need to run post-delete selector if available eventManager.executeEvent( new DescriptorEvent(DescriptorEventManager.PostDeleteEvent, this)); } if (!isUnitOfWork) { session.commitTransaction(); } commitManager.markCommitCompleted(object); // CR3510313, avoid removing aggregate collections from cache (maintain cache is false). if (shouldMaintainCache()) { if (isUnitOfWork) { ((UnitOfWorkImpl) session).addObjectDeletedDuringCommit(object, descriptor); } else { session .getIdentityMapAccessorInstance() .removeFromIdentityMap( getPrimaryKey(), descriptor.getJavaClass(), descriptor, object); } } return object; } catch (RuntimeException exception) { if (!isUnitOfWork) { session.rollbackTransaction(); } commitManager.markCommitCompleted(object); throw exception; } }