/** * PUBLIC: * Return true if the receiver uses version optimistic locking. */ public boolean usesVersionLocking() { return (usesOptimisticLocking() && (getOptimisticLockingPolicy() instanceof VersionLockingPolicy)); }
/** * Build the row representation of the object for update. The row built does not * contain entries for uninstantiated attributes. */ public AbstractRecord buildTemplateUpdateRow(AbstractSession session) { AbstractRecord databaseRow = createRecord(); for (Iterator mappings = getNonPrimaryKeyMappings().iterator(); mappings.hasNext();) { DatabaseMapping mapping = (DatabaseMapping)mappings.next(); mapping.writeUpdateFieldsIntoRow(databaseRow, session); } if (getDescriptor().usesOptimisticLocking()) { getDescriptor().getOptimisticLockingPolicy().addLockFieldsToUpdateRow(databaseRow, session); } return databaseRow; }
/** * Build and return the expression to use as the where clause to an update object. * The row is passed to allow the version number to be extracted from it. */ public Expression buildUpdateExpression(DatabaseTable table, AbstractRecord transactionRow, AbstractRecord modifyRow) { // Only the first table must use the lock check. Expression primaryKeyExpression = buildPrimaryKeyExpression(table); if (getDescriptor().usesOptimisticLocking()) { return getDescriptor().getOptimisticLockingPolicy().buildUpdateExpression(table, primaryKeyExpression, transactionRow, modifyRow); } else { return primaryKeyExpression; } }
/** * INTERNAL: * Prepare the receiver for execution in a session. In particular, * verify that the object is not null and contains a valid primary key. */ public void prepareForExecution() throws QueryException { super.prepareForExecution(); // Add the write lock field if required if (getDescriptor().usesOptimisticLocking()) { getDescriptor().getOptimisticLockingPolicy().addLockValuesToTranslationRow(this); } } }
/** * Add the initial write lock value to the row for insert. */ protected void addWriteLockFieldForInsert() { if (getDescriptor().usesOptimisticLocking()) { getDescriptor().getOptimisticLockingPolicy().setupWriteFieldsForInsert(getWriteObjectQuery()); } }
/** * Build and return the expression to use as the where clause to delete an object. * The row is passed to allow the version number to be extracted from it. */ public Expression buildDeleteExpression(DatabaseTable table, AbstractRecord row) { if (getDescriptor().usesOptimisticLocking() && (getDescriptor().getTables().firstElement().equals(table))) { return getDescriptor().getOptimisticLockingPolicy().buildDeleteExpression(table, primaryKeyExpression, row); } else { return buildPrimaryKeyExpression(table); } }
/** * INTERNAL: * Create ObjectChangeSet */ public ObjectChangeSet createObjectChangeSetThroughComparison(Object clone, Object backUp, oracle.toplink.essentials.internal.sessions.UnitOfWorkChangeSet changeSet, boolean isNew, AbstractSession session, ClassDescriptor descriptor) { ObjectBuilder builder = descriptor.getObjectBuilder(); ObjectChangeSet changes = builder.createObjectChangeSet(clone, changeSet, isNew, session); // The following code deals with reads that force changes to the flag associated with optimistic locking. if ((descriptor.usesOptimisticLocking()) && (changes.getPrimaryKeys() != null)) { changes.setOptimisticLockingPolicyAndInitialWriteLockValue(descriptor.getOptimisticLockingPolicy(), session); } // PERF: Avoid synchronized enumerator as is concurrency bottleneck. Vector mappings = descriptor.getMappings(); int mappingsSize = mappings.size(); for (int index = 0; index < mappingsSize; index++) { DatabaseMapping mapping = (DatabaseMapping)mappings.get(index); changes.addChange(mapping.compareForChange(clone, backUp, changes, session)); } return changes; }
/** * Initialize a cache key. Called by buildObject and now also by * buildWorkingCopyCloneFromRow. */ protected void copyQueryInfoToCacheKey(CacheKey cacheKey, ObjectBuildingQuery query, AbstractRecord databaseRow, AbstractSession session, ClassDescriptor concreteDescriptor) { //CR #4365 - used to prevent infinit recursion on refresh object cascade all cacheKey.setLastUpdatedQueryId(query.getQueryId()); if (concreteDescriptor.usesOptimisticLocking()) { OptimisticLockingPolicy policy = concreteDescriptor.getOptimisticLockingPolicy(); Object cacheValue = policy.getValueToPutInCache(databaseRow, session); //register the object into the IM and set the write lock object cacheKey.setWriteLockValue(cacheValue); } cacheKey.setReadTime(query.getExecutionTime()); }
if (descriptor.usesVersionLocking()) { VersionLockingPolicy vPolicy = VersionLockingPolicy.class .cast(descriptor.getOptimisticLockingPolicy()); if (mapping.getField() != null && vPolicy.getWriteLockFieldName().equals(
if (getOptimisticLockingPolicy() != null) { clonedDescriptor.setOptimisticLockingPolicy((OptimisticLockingPolicy)this.getOptimisticLockingPolicy().clone());
/** * Store the query object in the identity map. */ protected void registerObjectInIdentityMap() { WriteObjectQuery writeQuery = getWriteObjectQuery(); Object object = writeQuery.getObject(); if (writeQuery.shouldMaintainCache()) { if (getDescriptor().usesOptimisticLocking()) { Object optimisticLockValue = getDescriptor().getOptimisticLockingPolicy().getValueToPutInCache(writeQuery.getModifyRow(), getSession()); getSession().getIdentityMapAccessorInstance().putInIdentityMap(object, writeQuery.getPrimaryKey(), optimisticLockValue, System.currentTimeMillis(), getDescriptor()); } else { getSession().getIdentityMapAccessorInstance().putInIdentityMap(object, writeQuery.getPrimaryKey(), null, System.currentTimeMillis(), getDescriptor()); } } }
/** * Set the lock mode for an entity object contained in the persistence context. * @param entity * @param lockMode * @throws PersistenceException if an unsupported lock call is made * @throws IllegalArgumentException if the instance is not an entity or is a detached entity * @throws TransactionRequiredException if there is no transaction */ public void lock(Object entity, LockModeType lockMode){ try { verifyOpen(); RepeatableWriteUnitOfWork context = getActivePersistenceContext(checkForTransaction(!isExtended())); ClassDescriptor descriptor = context.getDescriptor(entity); OptimisticLockingPolicy lockingPolicy = descriptor.getOptimisticLockingPolicy(); if ((lockingPolicy == null) || !(lockingPolicy instanceof VersionLockingPolicy)){ throw new PersistenceException(ExceptionLocalization.buildMessage("ejb30-wrong-lock_called_without_version_locking-index", null)); } context.forceUpdateToVersionField(entity, (lockMode == LockModeType.WRITE)); } catch (RuntimeException e) { this.setRollbackOnly(); throw e; } }
OptimisticLockingPolicy lockingPolicy = getDescriptor().getOptimisticLockingPolicy(); if (query.shouldMaintainCache() && (lockingPolicy != null)) { lockingPolicy.prepareFetchGroupForReadQuery(query.getFetchGroup(), query);
public void buildTemplateInsertRow(AbstractSession session, AbstractRecord databaseRow) { for (Iterator mappings = getDescriptor().getMappings().iterator(); mappings.hasNext();) { DatabaseMapping mapping = (DatabaseMapping)mappings.next(); mapping.writeInsertFieldsIntoRow(databaseRow, session); } // If this descriptor is involved in inheritence add the class type. if (getDescriptor().hasInheritance()) { getDescriptor().getInheritancePolicy().addClassIndicatorFieldToInsertRow(databaseRow); } // If this descriptor has multiple tables then we need to append the primary keys for // the non default tables. if (!getDescriptor().isAggregateDescriptor()) { addPrimaryKeyForNonDefaultTable(databaseRow); } if (getDescriptor().usesOptimisticLocking()) { getDescriptor().getOptimisticLockingPolicy().addLockFieldsToUpdateRow(databaseRow, session); } //** sequencing refactoring if (getDescriptor().usesSequenceNumbers() && session.getSequencing().shouldAcquireValueAfterInsert(getDescriptor().getJavaClass())) { databaseRow.remove(getDescriptor().getSequenceNumberField()); } }
/** * Recursively merge to original from its parent into the clone. * The hastable is used to resolv recursion. */ protected Object mergeChangesOfOriginalIntoWorkingCopy(Object clone) { ClassDescriptor descriptor = getSession().getDescriptor(clone); // Find the original object, if it is not there then do nothing. Object original = ((UnitOfWorkImpl)getSession()).getOriginalVersionOfObjectOrNull(clone); if (original == null) { return clone; } // Merge into the clone from the original, use clone as backup as anything different should be merged. descriptor.getObjectBuilder().mergeIntoObject(clone, false, original, this); //update the change policies with the refresh descriptor.getObjectChangePolicy().revertChanges(clone, descriptor, (UnitOfWorkImpl)this.getSession(), ((UnitOfWorkImpl)this.getSession()).getCloneMapping()); Vector primaryKey = getSession().keyFromObject(clone); if (descriptor.usesOptimisticLocking()) { descriptor.getOptimisticLockingPolicy().mergeIntoParentCache((UnitOfWorkImpl)getSession(), primaryKey, clone); } CacheKey parentCacheKey = ((UnitOfWorkImpl)getSession()).getParent().getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey, clone.getClass(), descriptor); CacheKey uowCacheKey = getSession().getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey, clone.getClass(), descriptor); // Check for null because when there is NoIdentityMap, CacheKey will be null if ((parentCacheKey != null) && (uowCacheKey != null)) { uowCacheKey.setReadTime(parentCacheKey.getReadTime()); } return clone; }
/** * Clean up the cached object data and only revert the fetch group data back to the cached object. */ private void revertFetchGroupData(Object domainObject, ClassDescriptor concreteDescriptor, CacheKey cacheKey, ObjectBuildingQuery query, JoinedAttributeManager joinManager, AbstractRecord databaseRow, AbstractSession session) { //the cached object is either invalidated, or staled as the version is newer, or a refresh is explicitly set on the query. //clean all data of the cache object. concreteDescriptor.getFetchGroupManager().reset(domainObject); //read in the fetch group data only concreteDescriptor.getObjectBuilder().buildAttributesIntoObject(domainObject, databaseRow, query, joinManager, false); //set fetch group refrence to the cached object concreteDescriptor.getFetchGroupManager().setObjectFetchGroup(domainObject, query.getFetchGroup()); //set refresh on fetch group concreteDescriptor.getFetchGroupManager().setRefreshOnFetchGroupToObject(domainObject, (query.shouldRefreshIdentityMapResult() || concreteDescriptor.shouldAlwaysRefreshCache())); //set query id to prevent infinite recursion on refresh object cascade all cacheKey.setLastUpdatedQueryId(query.getQueryId()); //register the object into the IM and set the write lock object if applied. if (concreteDescriptor.usesOptimisticLocking()) { OptimisticLockingPolicy policy = concreteDescriptor.getOptimisticLockingPolicy(); cacheKey.setWriteLockValue(policy.getValueToPutInCache(databaseRow, session)); } cacheKey.setReadTime(query.getExecutionTime()); //validate the cached object cacheKey.setInvalidationState(CacheKey.CHECK_INVALIDATION_POLICY); }
getDescriptor().setOptimisticLockingPolicy((OptimisticLockingPolicy)getParentDescriptor().getOptimisticLockingPolicy().clone()); getDescriptor().getOptimisticLockingPolicy().setDescriptor(getDescriptor());
VersionLockingPolicy policy = (VersionLockingPolicy) descriptor.getOptimisticLockingPolicy(); if (policy.isStoredInObject()) { Object currentValue = builder.extractValueFromObjectForField(registeredObject, policy.getWriteLockField(), session);
OptimisticLockingPolicy policy = getDescriptor().getOptimisticLockingPolicy(); policy.addLockValuesToTranslationRow(writeQuery); getDescriptor().getOptimisticLockingPolicy().validateUpdate(rowCount, object, writeQuery);
getDescriptor().getOptimisticLockingPolicy().validateDelete(rowCount, object, writeQuery);