Search in sources :

Example 26 with UnitOfWorkImpl

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;
}
Also used : EntityFetchGroup(org.eclipse.persistence.internal.queries.EntityFetchGroup) ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) ObjectBuildingQuery(org.eclipse.persistence.queries.ObjectBuildingQuery) EntityFetchGroup(org.eclipse.persistence.internal.queries.EntityFetchGroup) FetchGroup(org.eclipse.persistence.queries.FetchGroup) UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl)

Example 27 with UnitOfWorkImpl

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();
}
Also used : SmallProject(org.eclipse.persistence.testing.models.employee.domain.SmallProject) Employee(org.eclipse.persistence.testing.models.employee.domain.Employee) ReadObjectQuery(org.eclipse.persistence.queries.ReadObjectQuery) UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl) CacheKey(org.eclipse.persistence.internal.identitymaps.CacheKey)

Example 28 with UnitOfWorkImpl

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;
}
Also used : QueryException(org.eclipse.persistence.exceptions.QueryException) ReadObjectQuery(org.eclipse.persistence.queries.ReadObjectQuery) ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) FieldExpression(org.eclipse.persistence.internal.expressions.FieldExpression) ConstantExpression(org.eclipse.persistence.internal.expressions.ConstantExpression) QueryKeyExpression(org.eclipse.persistence.internal.expressions.QueryKeyExpression) ParameterExpression(org.eclipse.persistence.internal.expressions.ParameterExpression) ObjectExpression(org.eclipse.persistence.internal.expressions.ObjectExpression) DataExpression(org.eclipse.persistence.internal.expressions.DataExpression) Expression(org.eclipse.persistence.expressions.Expression) UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl) FetchGroup(org.eclipse.persistence.queries.FetchGroup) InvalidObject(org.eclipse.persistence.internal.helper.InvalidObject) ExpressionBuilder(org.eclipse.persistence.expressions.ExpressionBuilder) CacheKey(org.eclipse.persistence.internal.identitymaps.CacheKey)

Example 29 with UnitOfWorkImpl

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);
}
Also used : Entry(java.util.Map.Entry) UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl) Map(java.util.Map)

Example 30 with UnitOfWorkImpl

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);
    }
}
Also used : UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl)

Aggregations

UnitOfWorkImpl (org.eclipse.persistence.internal.sessions.UnitOfWorkImpl)92 UnitOfWork (org.eclipse.persistence.sessions.UnitOfWork)21 TestErrorException (org.eclipse.persistence.testing.framework.TestErrorException)19 Employee (org.eclipse.persistence.testing.models.employee.domain.Employee)18 AbstractSession (org.eclipse.persistence.internal.sessions.AbstractSession)15 EntityManager (jakarta.persistence.EntityManager)14 InvalidObject (org.eclipse.persistence.internal.helper.InvalidObject)11 JpaEntityManager (org.eclipse.persistence.jpa.JpaEntityManager)9 Vector (java.util.Vector)8 ClassDescriptor (org.eclipse.persistence.descriptors.ClassDescriptor)8 Department (org.eclipse.persistence.testing.models.jpa.advanced.Department)8 CacheKey (org.eclipse.persistence.internal.identitymaps.CacheKey)7 EntityManagerImpl (org.eclipse.persistence.internal.jpa.EntityManagerImpl)7 ReadObjectQuery (org.eclipse.persistence.queries.ReadObjectQuery)7 DatabaseException (org.eclipse.persistence.exceptions.DatabaseException)6 UnitOfWorkChangeSet (org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet)6 EntityManagerFactory (jakarta.persistence.EntityManagerFactory)5 BigDecimal (java.math.BigDecimal)5 ExpressionBuilder (org.eclipse.persistence.expressions.ExpressionBuilder)5 ReadAllQuery (org.eclipse.persistence.queries.ReadAllQuery)5