Search in sources :

Example 1 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 2 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 3 with UnitOfWorkImpl

use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.

the class ExpressionBuilderTestSuite method testUnitOfWorkInExpressionBuilder.

// Bug# 429232 - Instance of UnitOfWork is stored in ExpressionBuilder inside ConcurrentFixedCache
// Make sure that [ExpressionBuilder].setSession() will not store UnitOfWork inside builder even
// when UnitOfWork is passed as an argument.
public void testUnitOfWorkInExpressionBuilder() {
    ExpressionBuilder builder = new ExpressionBuilder();
    UnitOfWorkImpl uow = (UnitOfWorkImpl) getSession().acquireUnitOfWork();
    builder.setSession(uow);
    AbstractSession session = builder.getSession();
    if (session instanceof UnitOfWork) {
        throw new TestErrorException("Session stored in ExpressionBuilder shall not be UnitOfWork.");
    }
}
Also used : UnitOfWork(org.eclipse.persistence.sessions.UnitOfWork) TestErrorException(org.eclipse.persistence.testing.framework.TestErrorException) UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl) ExpressionBuilder(org.eclipse.persistence.expressions.ExpressionBuilder) AbstractSession(org.eclipse.persistence.internal.sessions.AbstractSession)

Example 4 with UnitOfWorkImpl

use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.

the class ReadOnlyClassAccessingTestCase method test.

@Override
protected void test() {
    // Test acquiring a unit of work.
    UnitOfWork uow1 = getSession().acquireUnitOfWork();
    if (!uow1.getReadOnlyClasses().isEmpty()) {
        throw new TestErrorException(" When acquiring a UnitOfWork from a Session, the read-only classes where not empty as expected.");
    }
    uow1.release();
    // Test acquiring a unit of work with a vector of read-only classes.
    Vector classes = new Vector();
    classes.addElement(Promoter.class);
    classes.addElement(Country.class);
    UnitOfWork uow2 = getSession().acquireUnitOfWork();
    uow2.removeAllReadOnlyClasses();
    uow2.addReadOnlyClasses(classes);
    if (!areEqual(uow2.getReadOnlyClasses(), classes)) {
        throw new TestErrorException("When acquiring a UnitOfWork from a Session, the read-only classes specified did not get set in the UnitOfWork;");
    }
    // Test the testing of read-only classes
    for (Enumeration enumtr = classes.elements(); enumtr.hasMoreElements(); ) {
        if (!uow2.isClassReadOnly((Class) enumtr.nextElement())) {
            throw new TestErrorException("Testing whether a class is read-only or not has failed.");
        }
    }
    if (uow2.isClassReadOnly(Vector.class)) {
        throw new TestErrorException("Testing whether a class is read-only or not has failed.");
    }
    // Test the add and remove of read-only classes.
    uow2.removeReadOnlyClass(Promoter.class);
    if (uow2.isClassReadOnly(Promoter.class)) {
        throw new TestErrorException("The method removeReadOnlyClass(Class) failed.");
    }
    uow2.addReadOnlyClass(Promoter.class);
    if (!uow2.isClassReadOnly(Promoter.class)) {
        throw new TestErrorException("The method addReadOnlyClass(Class) failed.");
    }
    // Test the removeAll.
    uow2.removeAllReadOnlyClasses();
    if ((uow2.isClassReadOnly(Country.class)) || (!uow2.getReadOnlyClasses().isEmpty())) {
        throw new TestErrorException("Did not remove all the read-only classes from a UnitOfWork properly");
    }
    // Check that we cannot make  changes to the read-only set after registering an object.
    try {
        uow2.registerObject(new Address());
        uow2.removeAllReadOnlyClasses();
        uow2.addReadOnlyClasses(classes);
        if (areEqual(uow2.getReadOnlyClasses(), classes)) {
            throw new TestErrorException("Shouldn't be able to change the readOnlyClasses of a UnitOfWork after an object was registered.");
        }
    } catch (org.eclipse.persistence.exceptions.ValidationException ex) {
        getSession().logMessage("Caught validation exeception...OK");
    } finally {
        uow2.release();
    }
    // Check that the default read-only classes work.
    Vector someClasses = new Vector();
    someClasses.addElement(Country.class);
    someClasses.addElement(Address.class);
    getSession().getProject().setDefaultReadOnlyClasses(someClasses);
    UnitOfWork uow3 = getSession().acquireUnitOfWork();
    if (!areEqual(uow3.getReadOnlyClasses(), someClasses)) {
        throw new TestErrorException("The default read-only classes were not set properly when a UnitOfWork was aquired");
    }
    // Nested units of work should not be able to reduce the set of read-only classes.
    UnitOfWork uow4 = uow3.acquireUnitOfWork();
    try {
        uow4.removeAllReadOnlyClasses();
    } catch (org.eclipse.persistence.exceptions.ValidationException ex) {
        getSession().logMessage("Check the nested units of work read-only classes. OK");
    } finally {
        uow3.release();
        uow4.release();
    }
    // You should be able to get the default set of read-only classes from nested UnitOfWork objects.
    UnitOfWork uow5 = getSession().acquireUnitOfWork();
    UnitOfWork uow6 = uow5.acquireUnitOfWork();
    if (!areEqual(((UnitOfWorkImpl) uow5).getDefaultReadOnlyClasses(), ((UnitOfWorkImpl) uow6).getDefaultReadOnlyClasses()))
        throw new TestErrorException("Nested UnitOfWorks did not return consistent default read-only classes.");
    uow5.release();
    uow6.release();
}
Also used : Promoter(org.eclipse.persistence.testing.models.readonly.Promoter) Address(org.eclipse.persistence.testing.models.readonly.Address) UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl)

Example 5 with UnitOfWorkImpl

use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.

the class UnitOfWorkExistingObjectsListTest method test.

@Override
public void test() {
    Session session = getSession();
    UnitOfWork uow = session.acquireUnitOfWork();
    Address addr = (Address) uow.readObject(Address.class);
    uow.release();
    uow = session.acquireUnitOfWork();
    uow.setValidationLevel(UnitOfWorkImpl.None);
    Employee emp = new Employee();
    uow.registerNewObject(emp);
    emp.setAddress(addr);
    uow.assignSequenceNumbers();
    if (!((UnitOfWorkImpl) uow).getUnregisteredExistingObjects().containsKey(addr)) {
        throw new TestErrorException(" Bug 294259 -  Duplicate existence checks in same UOW.  Patch Failed");
    }
    uow.release();
}
Also used : UnitOfWork(org.eclipse.persistence.sessions.UnitOfWork) Employee(org.eclipse.persistence.testing.models.employee.domain.Employee) Address(org.eclipse.persistence.testing.models.employee.domain.Address) TestErrorException(org.eclipse.persistence.testing.framework.TestErrorException) UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl) Session(org.eclipse.persistence.sessions.Session)

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