use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.
the class AggregateObjectMapping method buildAggregateFromRow.
/**
* INTERNAL:
* Build and return an aggregate object from the specified row.
* If a null value is allowed and all the appropriate fields in the row are NULL, return a null.
* If an aggregate is referenced by the target object, return it (maintain identity)
* Otherwise, simply create a new aggregate object and return it.
*/
public Object buildAggregateFromRow(AbstractRecord databaseRow, Object targetObject, CacheKey cacheKey, JoinedAttributeManager joinManager, ObjectBuildingQuery sourceQuery, boolean buildShallowOriginal, AbstractSession executionSession, boolean targetIsProtected) throws DatabaseException {
if (databaseRow.hasSopObject()) {
Object sopAggregate = getAttributeValueFromObject(databaseRow.getSopObject());
if ((targetObject != null) && (targetObject != databaseRow.getSopObject())) {
setAttributeValueInObject(targetObject, sopAggregate);
}
return sopAggregate;
}
// check for all NULLs
if (isNullAllowed() && allAggregateFieldsAreNull(databaseRow)) {
return null;
}
// maintain object identity (even if not refreshing) if target object references the aggregate
// if aggregate is not referenced by the target object, construct a new aggregate
Object aggregate = null;
ClassDescriptor descriptor = getReferenceDescriptor();
boolean refreshing = true;
if (targetObject != null) {
if (descriptor.hasInheritance()) {
Class<?> newAggregateClass = descriptor.getInheritancePolicy().classFromRow(databaseRow, executionSession);
descriptor = getReferenceDescriptor(newAggregateClass, executionSession);
aggregate = getMatchingAttributeValueFromObject(databaseRow, targetObject, executionSession, descriptor);
if ((aggregate != null) && (aggregate.getClass() != newAggregateClass)) {
// if the class has changed out from underneath us, we cannot preserve object identity
// build a new instance of the *new* class
aggregate = descriptor.getObjectBuilder().buildNewInstance();
refreshing = false;
}
} else {
aggregate = getMatchingAttributeValueFromObject(databaseRow, targetObject, executionSession, descriptor);
}
}
// the passed cacheKey is null from the invalidation of the target object in the IdentityMap.
if (aggregate == null || (aggregate != null && cacheKey == null)) {
aggregate = descriptor.getObjectBuilder().buildNewInstance();
refreshing = false;
}
ObjectBuildingQuery nestedQuery = prepareNestedQuery(sourceQuery);
FetchGroup targetFetchGroup = null;
if (nestedQuery.isObjectLevelReadQuery()) {
targetFetchGroup = ((ObjectLevelReadQuery) nestedQuery).getFetchGroup();
if (refreshing && descriptor.hasFetchGroupManager()) {
descriptor.getFetchGroupManager().unionEntityFetchGroupIntoObject(aggregate, descriptor.getFetchGroupManager().getEntityFetchGroup(targetFetchGroup), executionSession, true);
// merge fetchgroup into aggregate fetchgroup that may have been there from previous read.
}
}
if (buildShallowOriginal) {
descriptor.getObjectBuilder().buildAttributesIntoShallowObject(aggregate, databaseRow, nestedQuery);
} else if (executionSession.isUnitOfWork()) {
descriptor.getObjectBuilder().buildAttributesIntoWorkingCopyClone(aggregate, buildWrapperCacheKeyForAggregate(cacheKey, targetIsProtected), nestedQuery, joinManager, databaseRow, (UnitOfWorkImpl) executionSession, refreshing);
} else {
descriptor.getObjectBuilder().buildAttributesIntoObject(aggregate, buildWrapperCacheKeyForAggregate(cacheKey, targetIsProtected), databaseRow, nestedQuery, joinManager, nestedQuery.getExecutionFetchGroup(descriptor), refreshing, executionSession);
}
if ((targetFetchGroup != null) && descriptor.hasFetchGroupManager() && cacheKey != null && !refreshing && sourceQuery.shouldMaintainCache() && !sourceQuery.shouldStoreBypassCache()) {
// Set the fetch group to the domain object, after built.
EntityFetchGroup entityFetchGroup = descriptor.getFetchGroupManager().getEntityFetchGroup(targetFetchGroup);
if (entityFetchGroup != null) {
entityFetchGroup = (EntityFetchGroup) entityFetchGroup.clone();
entityFetchGroup.setRootEntity((FetchGroupTracker) cacheKey.getObject());
entityFetchGroup.setOnEntity(aggregate, executionSession);
}
}
return aggregate;
}
use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.
the class Runner1 method run.
@Override
public void run() {
UnitOfWorkImpl uow = (UnitOfWorkImpl) this.session.acquireUnitOfWork();
ReadObjectQuery roq = new ReadObjectQuery(Employee.class);
roq.setSelectionCriteria(roq.getExpressionBuilder().get("id").equal(empPK));
Employee emp = (Employee) uow.executeQuery(roq);
roq = new ReadObjectQuery(SmallProject.class);
roq.setSelectionCriteria(roq.getExpressionBuilder().get("id").equal(projPK));
SmallProject project = (SmallProject) uow.executeQuery(roq);
emp.getProjects().add(project);
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
}
uow.issueSQLbeforeCompletion(true);
synchronized (this.waitOn) {
try {
this.waitOn.notify();
this.waitOn.wait();
} catch (InterruptedException e) {
}
}
CacheKey cacheKey = uow.getParent().getIdentityMapAccessorInstance().getCacheKeyForObject(emp);
synchronized (cacheKey) {
cacheKey.notify();
}
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
}
uow.mergeClonesAfterCompletion();
}
use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.
the class ExpressionQueryMechanism method checkCacheForObject.
/**
* Perform a cache lookup for the query
* This is only called from read object query.
* The query has already checked that the cache should be checked.
*/
@Override
public Object checkCacheForObject(AbstractRecord translationRow, AbstractSession session) {
// For bug 2782991 a list of nearly 20 problems with this method have
// been fixed.
ReadObjectQuery query = getReadObjectQuery();
ClassDescriptor descriptor = getDescriptor();
boolean conforming = false;
UnitOfWorkImpl uow = null;
if (session.isUnitOfWork()) {
conforming = query.shouldConformResultsInUnitOfWork() || descriptor.shouldAlwaysConformResultsInUnitOfWork();
uow = (UnitOfWorkImpl) session;
}
// Set the in memory query policy automatically for conforming queries, unless the
// user specifies the most cautious one.
int policyToUse = query.getInMemoryQueryIndirectionPolicyState();
if (conforming && (policyToUse != InMemoryQueryIndirectionPolicy.SHOULD_TRIGGER_INDIRECTION)) {
// Bug 320764 - return not conformed by default, to avoid incorrect results being returned
policyToUse = InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_NOT_CONFORMED;
}
Object cachedObject = null;
Expression selectionCriteria = getSelectionCriteria();
// Perform a series of cache checks, in the following order...
// 1: If selection key or selection object, lookup by primary key.
// 1.5: If row has sopObject, lookup by its primary key.
// 2: If selection criteria null, take the first instance in cache.
// 3: If exact primary key expression, lookup by primary key.
// 4: If inexact primary key expression, lookup by primary key and see if it conforms.
// 5: Perform a linear search on the cache, calling doesConform on each object.
// 6: (Conforming) Search through new objects.
// Each check is more optimal than the next.
// Finally: (Conforming) check that any positive result was not deleted in the UnitOfWork.
// 1: If selection key or selection object, do lookup by primary key.
Object selectionKey = query.getSelectionId();
Object selectionObject = query.getSelectionObject();
if ((selectionKey != null) || (selectionObject != null)) {
if (selectionKey == null) {
selectionKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(selectionObject, session, true);
if (selectionKey == null) {
// Has a null primary key, so must not exist.
return InvalidObject.instance;
}
// Must be checked separately as the expression and row is not yet set.
query.setSelectionId(selectionKey);
}
if (query.requiresDeferredLocks()) {
cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMapWithDeferredLock(selectionKey, query.getReferenceClass(), false, descriptor);
} else {
cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMap(selectionKey, query.getReferenceClass(), false, descriptor);
}
} else {
//
if (translationRow != null && translationRow.hasSopObject()) {
if (query.requiresDeferredLocks()) {
cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMapWithDeferredLock(descriptor.getObjectBuilder().extractPrimaryKeyFromObject(translationRow.getSopObject(), session), query.getReferenceClass(), false, descriptor);
} else {
cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMap(descriptor.getObjectBuilder().extractPrimaryKeyFromObject(translationRow.getSopObject(), session), query.getReferenceClass(), false, descriptor);
}
} else {
//
if (selectionCriteria == null) {
// In future would like to always return something from cache.
if (query.shouldConformResultsInUnitOfWork() || descriptor.shouldAlwaysConformResultsInUnitOfWork() || query.shouldCheckCacheOnly() || query.shouldCheckCacheThenDatabase()) {
cachedObject = session.getIdentityMapAccessorInstance().getFromIdentityMap(null, query.getReferenceClass(), translationRow, policyToUse, conforming, false, descriptor);
}
} else {
// 3: If can extract exact primary key expression, do lookup by primary key.
//
selectionKey = descriptor.getObjectBuilder().extractPrimaryKeyFromExpression(true, selectionCriteria, translationRow, session);
// primary key only this will become the final check.
if ((selectionKey != null) || query.shouldCheckCacheByExactPrimaryKey()) {
if (selectionKey != null) {
// Check if key is invalid (null), cannot exist.
if (selectionKey == InvalidObject.instance) {
return selectionKey;
}
if (query.requiresDeferredLocks()) {
cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMapWithDeferredLock(selectionKey, query.getReferenceClass(), false, descriptor);
} else {
cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMap(selectionKey, query.getReferenceClass(), false, descriptor);
}
// Because it was exact primary key if the lookup failed then it is not there.
}
} else {
// 4: If can extract inexact primary key, find one object by primary key and
// check if it conforms. Failure of this object to conform however does not
// rule out a cache hit.
// Check for any primary key in expression, may have other stuff.
Object inexactSelectionKey = descriptor.getObjectBuilder().extractPrimaryKeyFromExpression(false, selectionCriteria, translationRow, session);
if (inexactSelectionKey != null) {
// Check if key is invalid (null), cannot exist.
if (selectionKey == InvalidObject.instance) {
return selectionKey;
}
// PERF: Only use deferred lock when required.
if (query.requiresDeferredLocks()) {
cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMapWithDeferredLock(inexactSelectionKey, query.getReferenceClass(), false, descriptor);
} else {
cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMap(inexactSelectionKey, query.getReferenceClass(), false, descriptor);
}
} else {
CacheKey cacheKey = descriptor.getCachePolicy().checkCacheByIndex(selectionCriteria, translationRow, descriptor, session);
if (cacheKey != null) {
if (query.requiresDeferredLocks()) {
cacheKey.checkDeferredLock();
} else {
cacheKey.checkReadLock();
}
cachedObject = cacheKey.getObject();
}
}
if (cachedObject != null) {
// Must ensure that it matches the expression.
try {
// PERF: 3639015 - cloning the expression no longer required
// when using the root session.
ExpressionBuilder builder = selectionCriteria.getBuilder();
builder.setSession(session.getRootSession(null));
builder.setQueryClass(descriptor.getJavaClass());
if (!selectionCriteria.doesConform(cachedObject, session, translationRow, policyToUse)) {
cachedObject = null;
}
} catch (QueryException exception) {
// Ignore if expression too complex.
if (query.shouldCheckCacheOnly()) {
// Throw on only cache.
throw exception;
}
cachedObject = null;
}
}
// 5: Perform a linear search of the cache, calling expression.doesConform on each element.
// This is a last resort linear time search of the identity map.
// This can be avoided by setting check cache by (inexact/exact) primary key on the query.
// That flag becomes invalid in the conforming case (bug 2609611: SUPPORT CONFORM RESULT IN UOW IN CONJUNCTION WITH OTHER IN-MEMORY FEATURES)
// so if conforming must always do this linear search, but at least only on
// objects registered in the UnitOfWork.
//
boolean conformingButOutsideUnitOfWork = ((query.shouldConformResultsInUnitOfWork() || descriptor.shouldAlwaysConformResultsInUnitOfWork()) && !session.isUnitOfWork());
if ((cachedObject == null) && (conforming || (!query.shouldCheckCacheByPrimaryKey() && !conformingButOutsideUnitOfWork))) {
// when using the root session
if (selectionCriteria != null) {
ExpressionBuilder builder = selectionCriteria.getBuilder();
builder.setSession(session.getRootSession(null));
builder.setQueryClass(descriptor.getJavaClass());
}
try {
cachedObject = session.getIdentityMapAccessorInstance().getFromIdentityMap(selectionCriteria, query.getReferenceClass(), translationRow, policyToUse, conforming, false, descriptor);
} catch (QueryException exception) {
// Ignore if expression too complex.
if (query.shouldCheckCacheOnly()) {
// Throw on only cache.
throw exception;
}
}
}
}
}
}
}
//
if (conforming) {
if (cachedObject == null) {
if (selectionKey != null) {
cachedObject = uow.getObjectFromNewObjects(query.getReferenceClass(), selectionKey);
} else {
// when using the root session
if (selectionCriteria != null) {
ExpressionBuilder builder = selectionCriteria.getBuilder();
builder.setSession(session.getRootSession(null));
builder.setQueryClass(descriptor.getJavaClass());
}
try {
cachedObject = uow.getObjectFromNewObjects(selectionCriteria, query.getReferenceClass(), translationRow, policyToUse);
} catch (QueryException exception) {
// Ignore if expression too complex.
}
}
}
//
if (cachedObject != null) {
if (uow.isObjectDeleted(cachedObject)) {
if (selectionKey != null) {
// that the object was found but null must be returned.
return InvalidObject.instance;
} else {
cachedObject = null;
}
}
}
}
if (cachedObject != null) {
// Fetch group check, ensure object is fetched.
if (descriptor.hasFetchGroupManager()) {
if (descriptor.getFetchGroupManager().isPartialObject(cachedObject)) {
FetchGroup fetchGroup = query.getExecutionFetchGroup(descriptor);
EntityFetchGroup entityFetchGroup = null;
if (fetchGroup != null) {
entityFetchGroup = descriptor.getFetchGroupManager().getEntityFetchGroup(fetchGroup);
}
if (!descriptor.getFetchGroupManager().isObjectValidForFetchGroup(cachedObject, entityFetchGroup)) {
// the cached object is partially fetched, and it's fetch group is not a superset of the one in the query, so the cached object is not valid for the query.
cachedObject = null;
}
}
}
}
// in which case the parent cache still needs to be checked.
if ((cachedObject == null) && query.shouldCheckCacheOnly() && ((uow == null) || (!uow.isNestedUnitOfWork() && descriptor.getCachePolicy().shouldIsolateObjectsInUnitOfWork()))) {
return InvalidObject.instance;
}
return cachedObject;
}
use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.
the class MapContainerPolicy method addNextValueFromIteratorInto.
/**
* INTERNAL:
* This method is used to add the next value from an iterator built using ContainerPolicy's iteratorFor() method
* into the toCollection. Since this ContainerPolicy represents a Map, the key and the value are extracted and added.
*/
@Override
public void addNextValueFromIteratorInto(Object valuesIterator, Object parent, CacheKey parentCacheKey, Object toCollection, CollectionMapping mapping, Integer refreshCascade, AbstractSession cloningSession, boolean isExisting, boolean isFromSharedCache) {
Map.Entry entry = ((MapContainerPolicyIterator) valuesIterator).next();
Object clonedKey = buildCloneForKey(entry.getKey(), parent, parentCacheKey, refreshCascade, cloningSession, isExisting, isFromSharedCache);
Object clonedValue = buildCloneForValue(entry.getValue(), parent, parentCacheKey, mapping, refreshCascade, cloningSession, isExisting, isFromSharedCache);
// uow should discover new objects
if (cloningSession.isUnitOfWork() && mapping.isCandidateForPrivateOwnedRemoval() && ((UnitOfWorkImpl) cloningSession).shouldDiscoverNewObjects()) {
if (clonedValue != null && ((UnitOfWorkImpl) cloningSession).isCloneNewObject(clonedValue)) {
((UnitOfWorkImpl) cloningSession).addPrivateOwnedObject(mapping, clonedValue);
}
}
addInto(clonedKey, clonedValue, toCollection, cloningSession);
}
use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.
the class AbstractTransformationMapping method buildShallowOriginalFromRow.
/**
* INTERNAL:
* Builds a shallow original object. Only direct attributes and primary
* keys are populated. In this way the minimum original required for
* instantiating a working copy clone can be built without placing it in
* the shared cache (no concern over cycles).
* @param original later the input to buildCloneFromRow
*/
@Override
public void buildShallowOriginalFromRow(AbstractRecord record, Object original, JoinedAttributeManager joinManager, ObjectBuildingQuery query, AbstractSession executionSession) {
// In this case we know it is a primary key mapping, so hope that it
// is essentially a direct mapping. If it is a 1-1 with a
// no-indirection pointer back to original, then will get a stack
// overflow.
// Only solution to this is to trigger the transformation using the root
// session.
UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl) query.getSession();
query.setSession(unitOfWork.getParent());
try {
readFromRowIntoObject(record, joinManager, original, null, query, executionSession, false);
} finally {
query.setSession(unitOfWork);
}
}
Aggregations