/** * PUBLIC: * Returns true if the descriptor represents an isolated class */ public boolean isProtectedIsolation() { return getCachePolicy().isProtectedIsolation(); }
/** * PUBLIC: * Returns true if the descriptor represents an isolated class */ public boolean isProtectedIsolation() { return getCachePolicy().isProtectedIsolation(); }
/** * INTERNAL: * Clone the element, if necessary. */ public Object buildElementClone(Object element, Object parent, CacheKey parentCacheKey, Integer refreshCascade, AbstractSession cloningSession, boolean isExisting, boolean isFromSharedCache) { if (cloningSession.isUnitOfWork()){ return buildElementUnitOfWorkClone(element, parent, refreshCascade, (UnitOfWorkImpl)cloningSession, isExisting, isFromSharedCache); } if (referenceDescriptor.getCachePolicy().isProtectedIsolation()){ return cloningSession.createProtectedInstanceFromCachedData(element, refreshCascade, referenceDescriptor); } return element; }
/** * INTERNAL: * Clone the element, if necessary. */ public Object buildElementClone(Object element, Object parent, CacheKey parentCacheKey, Integer refreshCascade, AbstractSession cloningSession, boolean isExisting, boolean isFromSharedCache) { if (cloningSession.isUnitOfWork()){ return buildElementUnitOfWorkClone(element, parent, refreshCascade, (UnitOfWorkImpl)cloningSession, isExisting, isFromSharedCache); } if (referenceDescriptor.getCachePolicy().isProtectedIsolation()){ return cloningSession.createProtectedInstanceFromCachedData(element, refreshCascade, referenceDescriptor); } return element; }
/** * INTERNAL: * Require for cloning, the part must be cloned. * Ignore the objects, use the attribute value. */ @Override public Object buildCloneForPartObject(Object attributeValue, Object original, CacheKey cacheKey, Object clone, AbstractSession cloningSession, Integer refreshCascade, boolean isExisting, boolean isFromSharedCache) { if (attributeValue == null) { return null; } if (cloningSession.isUnitOfWork()){ return buildUnitofWorkCloneForPartObject(attributeValue, original, clone, refreshCascade, (UnitOfWorkImpl)cloningSession, isExisting); } // Not a unit Of Work clone so must have been a PROTECTED object if (this.referenceDescriptor.getCachePolicy().isProtectedIsolation()) { ClassDescriptor descriptor = this.referenceDescriptor; if (descriptor.hasInterfacePolicy()){ descriptor = cloningSession.getClassDescriptor(attributeValue.getClass()); } return cloningSession.createProtectedInstanceFromCachedData(attributeValue, refreshCascade, descriptor); } return attributeValue; }
/** * INTERNAL: * Require for cloning, the part must be cloned. * Ignore the objects, use the attribute value. */ @Override public Object buildCloneForPartObject(Object attributeValue, Object original, CacheKey cacheKey, Object clone, AbstractSession cloningSession, Integer refreshCascade, boolean isExisting, boolean isFromSharedCache) { if (attributeValue == null) { return null; } if (cloningSession.isUnitOfWork()){ return buildUnitofWorkCloneForPartObject(attributeValue, original, clone, refreshCascade, (UnitOfWorkImpl)cloningSession, isExisting); } // Not a unit Of Work clone so must have been a PROTECTED object if (this.referenceDescriptor.getCachePolicy().isProtectedIsolation()) { ClassDescriptor descriptor = this.referenceDescriptor; if (descriptor.hasInterfacePolicy()){ descriptor = cloningSession.getClassDescriptor(attributeValue.getClass()); } return cloningSession.createProtectedInstanceFromCachedData(attributeValue, refreshCascade, descriptor); } return attributeValue; }
/** * INTERNAL: * Returns the appropriate IdentityMap session for this descriptor. Sessions can be * chained and each session can have its own Cache/IdentityMap. Entities can be stored * at different levels based on Cache Isolation. This method will return the correct Session * for a particular Entity class based on the Isolation Level and the attributes provided. * <p> * @param canReturnSelf true when method calls itself. If the path * starting at <code>this</code> is acceptable. Sometimes true if want to * move to the first valid session, i.e. executing on ClientSession when really * should be on ServerSession. * @param terminalOnly return the last session in the chain where the Enitity is stored. * @return Session with the required IdentityMap */ @Override public AbstractSession getParentIdentityMapSession(ClassDescriptor descriptor, boolean canReturnSelf, boolean terminalOnly) { if (canReturnSelf && (descriptor == null || descriptor.getCachePolicy().isIsolated() || (descriptor.getCachePolicy().isProtectedIsolation() && !descriptor.shouldIsolateProtectedObjectsInUnitOfWork() && !terminalOnly))){ return this; } return getParent().getParentIdentityMapSession(descriptor, canReturnSelf, terminalOnly); }
/** * INTERNAL: * Returns the appropriate IdentityMap session for this descriptor. Sessions can be * chained and each session can have its own Cache/IdentityMap. Entities can be stored * at different levels based on Cache Isolation. This method will return the correct Session * for a particular Entity class based on the Isolation Level and the attributes provided. * <p> * @param canReturnSelf true when method calls itself. If the path * starting at <code>this</code> is acceptable. Sometimes true if want to * move to the first valid session, i.e. executing on ClientSession when really * should be on ServerSession. * @param terminalOnly return the last session in the chain where the Enitity is stored. * @return Session with the required IdentityMap */ @Override public AbstractSession getParentIdentityMapSession(ClassDescriptor descriptor, boolean canReturnSelf, boolean terminalOnly) { if (canReturnSelf && (descriptor == null || descriptor.getCachePolicy().isIsolated() || (descriptor.getCachePolicy().isProtectedIsolation() && !descriptor.shouldIsolateProtectedObjectsInUnitOfWork() && !terminalOnly))){ return this; } return getParent().getParentIdentityMapSession(descriptor, canReturnSelf, terminalOnly); }
/** * INTERNAL: * Extract value from the row and set the attribute to this value in the * working copy clone. * In order to bypass the shared cache when in transaction a UnitOfWork must * be able to populate working copies directly from the row. */ @Override public void buildCloneFromRow(AbstractRecord record, JoinedAttributeManager joinManager, Object clone, CacheKey sharedCacheKey, ObjectBuildingQuery sourceQuery, UnitOfWorkImpl unitOfWork, AbstractSession executionSession) { // If mapping is a no-attribute transformation mapping, do nothing if (isWriteOnly()) { return; } // This will set the value in the clone automatically. Object attributeValue = readFromRowIntoObject(record, joinManager, clone, sharedCacheKey, sourceQuery, executionSession, true); if (usesIndirection()) { boolean wasCacheUsed = this.isCacheable && sharedCacheKey != null && this.descriptor.getCachePolicy().isProtectedIsolation() && sharedCacheKey.getObject() != null; //it would be better if wasCacheUsed could be calculated within readFromRowIntoObject but that would require changing the signature of all mappings just for //transformation mapping. if (!wasCacheUsed){ //if the cache was used then the attribute has already been cloned by readFromRowIntoObject attributeValue = this.indirectionPolicy.cloneAttribute(attributeValue, null,// no original null, clone, null, unitOfWork, true);// build clone directly from row. } setAttributeValueInObject(clone, attributeValue); } }
/** * INTERNAL: * Extract value from the row and set the attribute to this value in the * working copy clone. * In order to bypass the shared cache when in transaction a UnitOfWork must * be able to populate working copies directly from the row. */ @Override public void buildCloneFromRow(AbstractRecord record, JoinedAttributeManager joinManager, Object clone, CacheKey sharedCacheKey, ObjectBuildingQuery sourceQuery, UnitOfWorkImpl unitOfWork, AbstractSession executionSession) { // If mapping is a no-attribute transformation mapping, do nothing if (isWriteOnly()) { return; } // This will set the value in the clone automatically. Object attributeValue = readFromRowIntoObject(record, joinManager, clone, sharedCacheKey, sourceQuery, executionSession, true); if (usesIndirection()) { boolean wasCacheUsed = this.isCacheable && sharedCacheKey != null && this.descriptor.getCachePolicy().isProtectedIsolation() && sharedCacheKey.getObject() != null; //it would be better if wasCacheUsed could be calculated within readFromRowIntoObject but that would require changing the signature of all mappings just for //transformation mapping. if (!wasCacheUsed){ //if the cache was used then the attribute has already been cloned by readFromRowIntoObject attributeValue = this.indirectionPolicy.cloneAttribute(attributeValue, null,// no original null, clone, null, unitOfWork, true);// build clone directly from row. } setAttributeValueInObject(clone, attributeValue); } }
if (this.descriptor.getCachePolicy().isProtectedIsolation()){ if (this.isCacheable && isTargetProtected && cacheKey != null){
/** * INTERNAL: * Return the mapping's attribute value from the row. * The execution session is passed for the case of building a UnitOfWork clone * directly from a row, the session set in the query will not know which platform to use * for converting the value. Allows the correct session to be passed in. */ @Override public Object valueFromRow(AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery query, CacheKey cacheKey, AbstractSession executionSession, boolean isTargetProtected, Boolean[] wasCacheUsed) { if (this.descriptor.getCachePolicy().isProtectedIsolation()) { if (this.isCacheable && isTargetProtected && cacheKey != null && cacheKey.getInvalidationState() != CacheKey.CACHE_KEY_INVALID) { Object cached = cacheKey.getObject(); if (cached != null) { if (wasCacheUsed != null){ wasCacheUsed[0] = Boolean.TRUE; } Object attributeValue = getAttributeValueFromObject(cached); return buildCloneValue(attributeValue, executionSession); } } } if (row.hasSopObject()) { return getAttributeValueFromObject(row.getSopObject()); } // PERF: Direct variable access. Object fieldValue = row.get(getField()); Object attributeValue = getObjectValue(fieldValue, executionSession); return attributeValue; }
/** * INTERNAL: * Return the mapping's attribute value from the row. * The execution session is passed for the case of building a UnitOfWork clone * directly from a row, the session set in the query will not know which platform to use * for converting the value. Allows the correct session to be passed in. */ public Object valueFromRow(AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery query, CacheKey cacheKey, AbstractSession executionSession, boolean isTargetProtected, Boolean[] wasCacheUsed, boolean lookupField) { if (this.descriptor.getCachePolicy().isProtectedIsolation()) { if (this.isCacheable && isTargetProtected && cacheKey != null && cacheKey.getInvalidationState() != CacheKey.CACHE_KEY_INVALID) { Object cached = cacheKey.getObject(); if (cached != null) { if (wasCacheUsed != null){ wasCacheUsed[0] = Boolean.TRUE; } Object attributeValue = getAttributeValueFromObject(cached); return buildCloneValue(attributeValue, executionSession); } } } if (row.hasSopObject()) { return getAttributeValueFromObject(row.getSopObject()); } // PERF: Direct variable access. Object fieldValue = row.get(getField(), lookupField); Object attributeValue = getObjectValue(fieldValue, executionSession); return attributeValue; } //cuba end
/** * INTERNAL: * Wrap the aggregate represented by this mapping in a cachekey so it can be processed my * methods down the stack. * @param owningCacheKey - the cache key holding the object to extract the aggregate from * @return */ protected CacheKey buildWrapperCacheKeyForAggregate(CacheKey owningCacheKey, boolean targetIsProtected) { if (!this.descriptor.getCachePolicy().isProtectedIsolation()) { return owningCacheKey; } if (!targetIsProtected || this.isMapKeyMapping || (owningCacheKey == null)) { return owningCacheKey; } CacheKey aggregateKey = owningCacheKey; Object object = owningCacheKey.getObject(); if (owningCacheKey.getObject() != null) { Object aggregate = getAttributeValueFromObject(object); aggregateKey = new CacheKey(null, aggregate, null); aggregateKey.setProtectedForeignKeys(owningCacheKey.getProtectedForeignKeys()); aggregateKey.setRecord(owningCacheKey.getRecord()); aggregateKey.setIsolated(owningCacheKey.isIsolated()); aggregateKey.setReadTime(owningCacheKey.getReadTime()); } return aggregateKey; }
/** * INTERNAL: * Wrap the aggregate represented by this mapping in a cachekey so it can be processed my * methods down the stack. * @param owningCacheKey - the cache key holding the object to extract the aggregate from * @return */ protected CacheKey buildWrapperCacheKeyForAggregate(CacheKey owningCacheKey, boolean targetIsProtected) { if (!this.descriptor.getCachePolicy().isProtectedIsolation()) { return owningCacheKey; } if (!targetIsProtected || this.isMapKeyMapping || (owningCacheKey == null)) { return owningCacheKey; } CacheKey aggregateKey = owningCacheKey; Object object = owningCacheKey.getObject(); if (owningCacheKey.getObject() != null) { Object aggregate = getAttributeValueFromObject(object); aggregateKey = new CacheKey(null, aggregate, null); aggregateKey.setProtectedForeignKeys(owningCacheKey.getProtectedForeignKeys()); aggregateKey.setRecord(owningCacheKey.getRecord()); aggregateKey.setIsolated(owningCacheKey.isIsolated()); aggregateKey.setReadTime(owningCacheKey.getReadTime()); } return aggregateKey; }
/** * INTERNAL: * Initialize the cache isolation setting. * This may need to be called multiple times as notifyReferencingDescriptorsOfIsolation() can change the cache isolation. */ public void postInitialize(ClassDescriptor descriptor, AbstractSession session) throws DescriptorException { if (!isSharedIsolation()) { descriptor.notifyReferencingDescriptorsOfIsolation(session); } // PERF: If using isolated cache, then default uow isolation to always (avoids merge/double build). if ((getUnitOfWorkCacheIsolationLevel() == UNDEFINED_ISOLATATION) || this.wasDefaultUnitOfWorkCacheIsolationLevel) { this.wasDefaultUnitOfWorkCacheIsolationLevel = true; if (isIsolated()) { setUnitOfWorkCacheIsolationLevel(ISOLATE_CACHE_ALWAYS); } else if (isProtectedIsolation()) { setUnitOfWorkCacheIsolationLevel(ISOLATE_FROM_CLIENT_SESSION); } else { setUnitOfWorkCacheIsolationLevel(ISOLATE_NEW_DATA_AFTER_TRANSACTION); } } // Record that there is an isolated class in the project. if (!isSharedIsolation()) { session.getProject().setHasIsolatedClasses(true); } if (!shouldIsolateObjectsInUnitOfWork() && !descriptor.shouldBeReadOnly()) { session.getProject().setHasNonIsolatedUOWClasses(true); } }
/** * INTERNAL: * Initialize the cache isolation setting. * This may need to be called multiple times as notifyReferencingDescriptorsOfIsolation() can change the cache isolation. */ public void postInitialize(ClassDescriptor descriptor, AbstractSession session) throws DescriptorException { if (!isSharedIsolation()) { descriptor.notifyReferencingDescriptorsOfIsolation(session); } // PERF: If using isolated cache, then default uow isolation to always (avoids merge/double build). if ((getUnitOfWorkCacheIsolationLevel() == UNDEFINED_ISOLATATION) || this.wasDefaultUnitOfWorkCacheIsolationLevel) { this.wasDefaultUnitOfWorkCacheIsolationLevel = true; if (isIsolated()) { setUnitOfWorkCacheIsolationLevel(ISOLATE_CACHE_ALWAYS); } else if (isProtectedIsolation()) { setUnitOfWorkCacheIsolationLevel(ISOLATE_FROM_CLIENT_SESSION); } else { setUnitOfWorkCacheIsolationLevel(ISOLATE_NEW_DATA_AFTER_TRANSACTION); } } // Record that there is an isolated class in the project. if (!isSharedIsolation()) { session.getProject().setHasIsolatedClasses(true); } if (!shouldIsolateObjectsInUnitOfWork() && !descriptor.shouldBeReadOnly()) { session.getProject().setHasNonIsolatedUOWClasses(true); } }
if (descriptor.getCachePolicy().isProtectedIsolation()) { if (parentSession.isIsolatedClientSession()){
if (this.descriptor.getCachePolicy().isProtectedIsolation()) { if (this.isCacheable && isTargetProtected && cacheKey != null) {
return null; if (this.descriptor.getCachePolicy().isProtectedIsolation()) { if (this.isCacheable && isTargetProtected && parentCacheKey != null) { Object cached = parentCacheKey.getObject();