/** * INTERNAL: * Update the parent write lock value if the unit of works has been incremented. */ public boolean isChildWriteLockValueGreater(AbstractSession session, java.util.Vector primaryKey, Class original, ObjectChangeSet changeSet) { if (isStoredInCache()) { // If this uow changed the object the version must be updated, // we can check this by ensuring our value is greater than our parent's. Number writeLockValue = (Number)changeSet.getWriteLockValue(); Number parentValue = (Number)session.getIdentityMapAccessor().getWriteLockValue(primaryKey, original); if ((parentValue != null) && (!(parentValue instanceof BigDecimal))) { parentValue = new BigDecimal(parentValue.longValue()); } if ((writeLockValue != null) && (!(writeLockValue instanceof BigDecimal))) { writeLockValue = new BigDecimal(writeLockValue.longValue()); } if (writeLockValue != null) {// This occurs if the object was deleted if ((parentValue == null) || (((BigDecimal)parentValue).compareTo((BigDecimal)writeLockValue) == -1)) { return true; } } } return false; }
/** * INTERNAL: Merge the changes to all objects to the parent. */ protected void mergeChangesIntoParent() { if(classesToBeInvalidated != null) { // get identityMap of the parent ServerSession IdentityMapAccessor accessor = this.getParentIdentityMapSession(null, false, true).getIdentityMapAccessor(); Iterator<Class> it = classesToBeInvalidated.iterator(); while(it.hasNext()) { accessor.invalidateClass(it.next(), false); } classesToBeInvalidated = null; } flushClearCache = null; super.mergeChangesIntoParent(); }
/** * INTERNAL: * This method will return the optimistic lock value for the object */ public Object getWriteLockValue(Object domainObject, java.util.Vector primaryKey, AbstractSession session) { Number writeLockFieldValue; if (isStoredInCache()) { writeLockFieldValue = (Number)session.getIdentityMapAccessor().getWriteLockValue(primaryKey, domainObject.getClass()); } else { writeLockFieldValue = (Number)lockValueFromObject(domainObject); } return writeLockFieldValue; }
/** * INTERNAL: * Update the parent write lock value if the unit of works has been incremented. */ public boolean isChildWriteLockValueGreater(UnitOfWorkImpl uow, java.util.Vector primaryKey, Class original) { if (isStoredInCache()) { // If this uow changed the object the version must be updated, // we can check this by ensuring our value is greater than our parent's. Number writeLockValue = (Number)uow.getIdentityMapAccessor().getWriteLockValue(primaryKey, original); Number parentValue = (Number)uow.getParent().getIdentityMapAccessor().getWriteLockValue(primaryKey, original); if ((parentValue != null) && (!(parentValue instanceof BigDecimal))) { parentValue = new BigDecimal(parentValue.longValue()); } if ((writeLockValue != null) && (!(writeLockValue instanceof BigDecimal))) { writeLockValue = new BigDecimal(writeLockValue.longValue()); } if (writeLockValue != null) {// This occurs if the object was deleted if ((parentValue == null) || (((BigDecimal)parentValue).compareTo((BigDecimal)writeLockValue) == -1)) { return true; } } } return false; }
/** * INTERNAL: * Only applicable when the value is stored in the cache. Will merge with the parent unit of work. */ public void mergeIntoParentCache(UnitOfWorkImpl uow, Vector primaryKey, Object object) { if (isStoredInCache()) { Object parentValue = uow.getParent().getIdentityMapAccessor().getWriteLockValue(primaryKey, object.getClass()); uow.getIdentityMapAccessor().updateWriteLockValue(primaryKey, object.getClass(), parentValue); } }
/** * Remove object represent this change set from identity map. If change set is in XML format, rebuild pk to the correct class type from String */ protected void removeFromIdentityMap(AbstractSession session) { session.getIdentityMapAccessor().removeFromIdentityMap(getPrimaryKeys(), getClassType(session)); }
Number newWriteLockFieldValue = (Number)databaseRow.get(getWriteLockField()); if (isStoredInCache()) { writeLockFieldValue = (Number)session.getIdentityMapAccessor().getWriteLockValue(primaryKey, domainObject.getClass()); } else { writeLockFieldValue = (Number)lockValueFromObject(domainObject);
/** * INTERNAL: * Return the number of versions different between these objects. */ public int getVersionDifference(Object currentValue, Object domainObject, Vector primaryKeys, AbstractSession session) { java.sql.Timestamp writeLockFieldValue; java.sql.Timestamp newWriteLockFieldValue = (java.sql.Timestamp)currentValue; if (newWriteLockFieldValue == null) { return 0;//merge it as either the object is new or being forced merged. } if (isStoredInCache()) { writeLockFieldValue = (java.sql.Timestamp)session.getIdentityMapAccessor().getWriteLockValue(primaryKeys, domainObject.getClass()); } else { writeLockFieldValue = (java.sql.Timestamp)lockValueFromObject(domainObject); } if ((writeLockFieldValue != null) && !(newWriteLockFieldValue.after(writeLockFieldValue))) { return 0; } //if the new value is newer then perform the update. Eventually this will be changed to //record the old version and compare that for equality return 2; }
/** * INTERNAL: * Reset the entire object cache, * ** be careful using this. * This method blows away both this session's and its parents caches, * this includes the server cache or any other cache. * This throws away any objects that have been read in. * Extreme caution should be used before doing this because object identity will no longer * be maintained for any objects currently read in. This should only be called * if the application knows that it no longer has references to object held in the cache. */ public void initializeAllIdentityMaps() { super.initializeAllIdentityMaps(); ((UnitOfWorkImpl)getSession()).getParent().getIdentityMapAccessor().initializeAllIdentityMaps(); } }
/** * INTERNAL: * This method updates the modify row, and the domain object * with the new lock value. * * #see this method in VersionLockingPolicy */ public void updateRowAndObjectForUpdate(ObjectLevelModifyQuery query, Object domainObject) { Object lockValue = getNewLockValue(query); if (isStoredInCache()) { query.getSession().getIdentityMapAccessor().updateWriteLockValue(query.getPrimaryKey(), domainObject.getClass(), lockValue); } updateWriteLockValueForWrite(query, lockValue); }
/** * INTERNAL: * This method will return the optimistic lock value for the object */ public Object getWriteLockValue(Object domainObject, java.util.Vector primaryKey, AbstractSession session) { java.sql.Timestamp writeLockFieldValue = null; if (isStoredInCache()) { writeLockFieldValue = (java.sql.Timestamp)session.getIdentityMapAccessor().getWriteLockValue(primaryKey, domainObject.getClass()); } else { //CR#2281 notStoredInCache prevent ClassCastException Object lockValue = lockValueFromObject(domainObject); if (lockValue != null) { if (lockValue instanceof java.sql.Timestamp) { writeLockFieldValue = (java.sql.Timestamp)lockValueFromObject(domainObject); } else { throw OptimisticLockException.needToMapJavaSqlTimestampWhenStoredInObject(); } } } return writeLockFieldValue; }
/** * INTERNAL: * Update the parent write lock value if the objectChangeSet's is greater. */ public boolean isChildWriteLockValueGreater(AbstractSession session, java.util.Vector primaryKey, Class original, ObjectChangeSet changeSet) { if (isStoredInCache()) { // If this uow changed the object the version must be updated, // we can check this by ensuring our value is greater than our parent's. java.sql.Timestamp writeLockValue = (java.sql.Timestamp)changeSet.getWriteLockValue(); java.sql.Timestamp parentValue = (java.sql.Timestamp)session.getIdentityMapAccessor().getWriteLockValue(primaryKey, original); if (writeLockValue != null) {// This occurs if the object was deleted if ((parentValue == null) || parentValue.before(writeLockValue)) {// Check parent value is less than child return true; } } } return false; }
/** * INTERNAL: * Remove objects from parent's identity map. */ protected void postMergeChanges() { //bug 4730595: objects removed during flush are not removed from the cache during commit if (!this.getUnitOfWorkChangeSet().getDeletedObjects().isEmpty()){ oracle.toplink.essentials.internal.helper.IdentityHashtable deletedObjects = this.getUnitOfWorkChangeSet().getDeletedObjects(); for (Enumeration removedObjects = deletedObjects.keys(); removedObjects.hasMoreElements(); ) { ObjectChangeSet removedObjectChangeSet = (ObjectChangeSet) removedObjects.nextElement(); java.util.Vector primaryKeys = removedObjectChangeSet.getPrimaryKeys(); getParent().getIdentityMapAccessor().removeFromIdentityMap(primaryKeys, removedObjectChangeSet.getClassType(this)); } } }
/** * INTERNAL: * This method updates the modify row with the old lock value. */ public void writeLockValueIntoRow(ObjectLevelModifyQuery query, Object domainObject) { Object lockValue = getWriteLockValue(domainObject, query.getPrimaryKey(), query.getSession()); query.getModifyRow().put(getWriteLockField(), lockValue); if (isStoredInCache()) { query.getSession().getIdentityMapAccessor().updateWriteLockValue(query.getPrimaryKey(), domainObject.getClass(), lockValue); } }
/** * INTERNAL: * Update the parent write lock value if the unit of works has been incremented. */ public boolean isChildWriteLockValueGreater(UnitOfWorkImpl uow, java.util.Vector primaryKey, Class original) { if (isStoredInCache()) { // If this uow changed the object the version must be updated, // we can check this by ensuring our value is greater than our parent's. java.sql.Timestamp writeLockValue = (java.sql.Timestamp)uow.getIdentityMapAccessor().getWriteLockValue(primaryKey, original); java.sql.Timestamp parentValue = (java.sql.Timestamp)uow.getParent().getIdentityMapAccessor().getWriteLockValue(primaryKey, original); if (writeLockValue != null) {// This occurs if the object was deleted if ((parentValue == null) || parentValue.before(writeLockValue)) {// Check parent value is less than child return true; } } } return false; }
/** * INTERNAL: * Compares the value from the row and from the object (or cache). * Will return true if the object is newer than the row. */ public boolean isNewerVersion(AbstractRecord databaseRow, Object domainObject, java.util.Vector primaryKey, AbstractSession session) { java.sql.Timestamp writeLockFieldValue; java.sql.Timestamp newWriteLockFieldValue = (java.sql.Timestamp)session.getDatasourcePlatform().convertObject(databaseRow.get(getWriteLockField()), ClassConstants.TIMESTAMP); if (isStoredInCache()) { writeLockFieldValue = (java.sql.Timestamp)session.getIdentityMapAccessor().getWriteLockValue(primaryKey, domainObject.getClass()); } else { writeLockFieldValue = (java.sql.Timestamp)lockValueFromObject(domainObject); } // bug 6342382: object's lock value is null, it is NOT newer than any newWriteLockFieldValue. if(writeLockFieldValue == null) { return false; } // 2.5.1.6 if the write lock value is null, then what ever we have is treated as newer. if (newWriteLockFieldValue == null) { return true; } if (!(newWriteLockFieldValue.after(writeLockFieldValue))) { return false; } return true; }
/** * INTERNAL: * This method adds the lock value to the translation row of the * passed in query. depending on the storage flag, the value is * either retrieved from the cache of the object. */ public void addLockValuesToTranslationRow(ObjectLevelModifyQuery query) { Object value; if (isStoredInCache()) { value = query.getSession().getIdentityMapAccessor().getWriteLockValue(query.getPrimaryKey(), query.getObject().getClass()); } else { value = lockValueFromObject(query.getObject()); } if (value == null) { if (query.isDeleteObjectQuery()) { throw OptimisticLockException.noVersionNumberWhenDeleting(query.getObject(), query); } else { throw OptimisticLockException.noVersionNumberWhenUpdating(query.getObject(), query); } } query.getTranslationRow().put(getWriteLockField(), value); }
/** * INTERNAL: * This method gets the write lock value from either the cache or * the object stored in the query. It then returns the new incremented value. */ protected Object getNewLockValue(ModifyQuery query) { Class objectClass = query.getDescriptor().getJavaClass(); Number value; Number newWriteLockValue = null; if (isStoredInCache()) { value = (Number)query.getSession().getIdentityMapAccessor().getWriteLockValue(((WriteObjectQuery)query).getPrimaryKey(), objectClass); } else { value = (Number)lockValueFromObject(((ObjectLevelModifyQuery)query).getObject()); } if (value == null) { throw oracle.toplink.essentials.exceptions.OptimisticLockException.noVersionNumberWhenUpdating(((ObjectLevelModifyQuery)query).getObject(), (ObjectLevelModifyQuery)query); } // Increment the value, this goes to the database newWriteLockValue = incrementWriteLockValue(value); return newWriteLockValue; }
/** * This is used for a remote unit of work. * If the value holder is sent back to the server uninstantiated and * it needs to be instantiated, then we must find the original * object and get the appropriate attribute from it. */ protected Object getValueFromServerObject() { setSession(getRemoteUnitOfWork()); Vector primaryKey = getSession().keyFromObject(getSourceObject()); Object originalObject = getUnitOfWork().getParent().getIdentityMapAccessor().getFromIdentityMap(primaryKey, getSourceObject().getClass()); if (originalObject == null) { originalObject = getUnitOfWork().getParent().readObject(getSourceObject()); } ClassDescriptor descriptor = getSession().getDescriptor(originalObject); DatabaseMapping mapping = descriptor.getObjectBuilder().getMappingForAttributeName(getSourceAttributeName()); setMapping(mapping); return getMapping().getRealAttributeValueFromObject(originalObject, getSession()); }
/** * INTERNAL: * The cache check is done before the prepare as a hit will not require the work to be done. */ protected Object checkEarlyReturnImpl(AbstractSession session, AbstractRecord translationRow) { // Check for in-memory only query. if (shouldCheckCacheOnly()) { // assert !isReportQuery(); if (shouldUseWrapperPolicy()) { getContainerPolicy().setElementDescriptor(getDescriptor()); } // PERF: Fixed to not query each unit of work cache (is not conforming), // avoid hashtable and primary key indexing. // At some point we may need to support some kind of in-memory with conforming option, // but we do not currently allow this. AbstractSession rootSession = session; while (rootSession.isUnitOfWork()) { rootSession = ((UnitOfWorkImpl)rootSession).getParent(); } Vector allCachedVector = rootSession.getIdentityMapAccessor().getAllFromIdentityMap(getSelectionCriteria(), getReferenceClass(), translationRow, getInMemoryQueryIndirectionPolicy(), false); // Must ensure that all of the objects returned are correctly registered in the unit of work. if (session.isUnitOfWork()) { allCachedVector = ((UnitOfWorkImpl)session).registerAllObjects(allCachedVector); } return getContainerPolicy().buildContainerFromVector(allCachedVector, session); } else { return null; } }