Search in sources :

Example 81 with UnitOfWorkImpl

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

the class ObjectLevelReadQuery method checkEarlyReturn.

/**
 * INTERNAL:
 * Check to see if this query already knows the return value without performing any further work.
 */
@Override
public Object checkEarlyReturn(AbstractSession session, AbstractRecord translationRow) {
    // For bug 3136413/2610803 building the selection criteria from an EJBQL string or
    // an example object is done just in time.
    // Also calls checkDescriptor here.
    // buildSelectionCriteria(session);
    checkPrePrepare(session);
    if (!session.isUnitOfWork()) {
        return checkEarlyReturnLocal(session, translationRow);
    }
    UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl) session;
    // The cache check must happen on the UnitOfWork in these cases either
    // to access transient state or for pessimistic locking, as only the
    // UOW knows which objects it has locked.
    Object result = null;
    // PERF: Avoid uow check for read-only.
    if (!this.descriptor.shouldBeReadOnly()) {
        result = checkEarlyReturnLocal(unitOfWork, translationRow);
    }
    if (result != null) {
        return result;
    }
    // An error should be thrown on prepare is checkCacheOnly is used with these.
    if ((!unitOfWork.isNestedUnitOfWork()) && (this.descriptor.getCachePolicy().shouldIsolateObjectsInUnitOfWork() || isLockQuery()) || unitOfWork.shouldForceReadFromDB(this, null)) {
        return null;
    }
    // follow the execution path in looking for the object.
    AbstractSession parentSession = unitOfWork.getParentIdentityMapSession(this);
    // assert parentSession != unitOfWork;
    result = checkEarlyReturn(parentSession, translationRow);
    if (result != null) {
        // treat this as cache hit but return null.  Bug 2782991.
        if (result == InvalidObject.instance) {
            return result;
        }
        Object clone = registerResultInUnitOfWork(result, unitOfWork, translationRow, false);
        if (shouldConformResultsInUnitOfWork() && unitOfWork.isObjectDeleted(clone)) {
            return InvalidObject.instance;
        }
        return clone;
    } else {
        return null;
    }
}
Also used : UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl) InvalidObject(org.eclipse.persistence.internal.helper.InvalidObject) AbstractSession(org.eclipse.persistence.internal.sessions.AbstractSession)

Example 82 with UnitOfWorkImpl

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

the class DeleteAllQuery method executeDatabaseQuery.

/**
 * INTERNAL:
 * Perform the work to delete a collection of objects.
 * This skips the optimistic lock check and should not called for objects using locking.
 * @exception  DatabaseException - an error has occurred on the database.
 * @return Integer the number of objects (rows) deleted.
 */
@Override
public Object executeDatabaseQuery() throws DatabaseException {
    // CR# 4286
    if (this.objects != null) {
        if (isExpressionQuery() && getSelectionCriteria() == null) {
            // DeleteAllQuery has objects so it *must* have selectionCriteria, too
            throw QueryException.deleteAllQuerySpecifiesObjectsButNotSelectionCriteria(getDescriptor(), this, this.objects.toString());
        }
        // Optimistic lock check not required because objects are deleted individually in that case.
        try {
            this.session.beginTransaction();
            // PERF: Avoid events if no listeners.
            if (this.descriptor.getEventManager().hasAnyEventListeners()) {
                for (Object object : this.objects) {
                    DescriptorEvent event = new DescriptorEvent(object);
                    event.setEventCode(DescriptorEventManager.PreDeleteEvent);
                    event.setSession(this.session);
                    event.setQuery(this);
                    this.descriptor.getEventManager().executeEvent(event);
                }
            }
            if (this.isInMemoryOnly) {
                result = 0;
            } else {
                result = this.queryMechanism.deleteAll();
            }
            // PERF: Avoid events if no listeners.
            if (this.descriptor.getEventManager().hasAnyEventListeners()) {
                for (Object object : this.objects) {
                    DescriptorEvent event = new DescriptorEvent(object);
                    event.setEventCode(DescriptorEventManager.PostDeleteEvent);
                    event.setSession(this.session);
                    event.setQuery(this);
                    this.descriptor.getEventManager().executeEvent(event);
                }
            }
            if (shouldMaintainCache()) {
                // remove from the cache.
                for (Object deleted : this.objects) {
                    if (this.session.isUnitOfWork()) {
                        // BUG #2612169: Unwrap is needed
                        deleted = this.descriptor.getObjectBuilder().unwrapObject(deleted, getSession());
                        ((UnitOfWorkImpl) this.session).addObjectDeletedDuringCommit(deleted, this.descriptor);
                    } else {
                        this.session.getIdentityMapAccessor().removeFromIdentityMap(deleted);
                    }
                }
            }
            this.session.commitTransaction();
        } catch (RuntimeException exception) {
            this.session.rollbackTransaction();
            throw exception;
        }
    } else {
        if (this.isInMemoryOnly) {
            result = 0;
        } else {
            // fire the SQL to the database
            result = this.queryMechanism.deleteAll();
        }
        mergeChangesIntoSharedCache();
    }
    return result;
}
Also used : UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl) DescriptorEvent(org.eclipse.persistence.descriptors.DescriptorEvent)

Example 83 with UnitOfWorkImpl

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

the class DeleteObjectQuery method executeDatabaseQuery.

/**
 * INTERNAL:
 * Perform the work to delete an object.
 * @return object - the object being deleted.
 */
@Override
public Object executeDatabaseQuery() throws DatabaseException, OptimisticLockException {
    AbstractSession session = getSession();
    CommitManager commitManager = session.getCommitManager();
    Object object = getObject();
    boolean isUnitOfWork = session.isUnitOfWork();
    try {
        // Check if the object has already been deleted, then no work is required.
        if (commitManager.isCommitCompletedInPostOrIgnore(object)) {
            return object;
        }
        ClassDescriptor descriptor = this.descriptor;
        // if it is, then there is a cycle, and the foreign keys must be nulled.
        if (commitManager.isCommitInPreModify(object)) {
            if (!commitManager.isShallowCommitted(object)) {
                getQueryMechanism().updateForeignKeyFieldBeforeDelete();
                if ((descriptor.getHistoryPolicy() != null) && descriptor.getHistoryPolicy().shouldHandleWrites()) {
                    descriptor.getHistoryPolicy().postUpdate(this);
                }
                commitManager.markShallowCommit(object);
            }
            return object;
        }
        commitManager.markPreModifyCommitInProgress(getObject());
        if (!isUnitOfWork) {
            session.beginTransaction();
        }
        DescriptorEventManager eventManager = descriptor.getEventManager();
        // PERF: Avoid events if no listeners.
        if (eventManager.hasAnyEventListeners()) {
            // Need to run pre-delete selector if available
            eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PreDeleteEvent, this));
        }
        // Verify if deep shallow modify is turned on
        if (shouldCascadeParts()) {
            descriptor.getQueryManager().preDelete(this);
        }
        // Check for deletion dependencies.
        if (isUnitOfWork) {
            Set<Object> dependencies = ((UnitOfWorkImpl) session).getDeletionDependencies(object);
            if (dependencies != null) {
                for (Object dependency : dependencies) {
                    if (!commitManager.isCommitCompletedInPostOrIgnore(dependency)) {
                        ClassDescriptor dependencyDescriptor = session.getDescriptor(dependency);
                        // PERF: Get the descriptor query, to avoid extra query creation.
                        DeleteObjectQuery deleteQuery = dependencyDescriptor.getQueryManager().getDeleteQuery();
                        if (deleteQuery == null) {
                            deleteQuery = new DeleteObjectQuery();
                            deleteQuery.setDescriptor(dependencyDescriptor);
                        } else {
                            // Ensure original query has been prepared.
                            deleteQuery.checkPrepare(session, deleteQuery.getTranslationRow());
                            deleteQuery = (DeleteObjectQuery) deleteQuery.clone();
                        }
                        deleteQuery.setIsExecutionClone(true);
                        deleteQuery.setObject(dependency);
                        session.executeQuery(deleteQuery);
                    }
                }
            }
        }
        // PERF: Avoid events if no listeners.
        if (eventManager.hasAnyEventListeners()) {
            DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToDeleteEvent, this);
            event.setRecord(getModifyRow());
            eventManager.executeEvent(event);
        }
        if (QueryMonitor.shouldMonitor()) {
            QueryMonitor.incrementDelete(this);
        }
        int rowCount = 0;
        // If the object was/will be deleted from a cascade delete constraint, ignore it.
        if (isUnitOfWork && ((UnitOfWorkImpl) session).hasCascadeDeleteObjects() && ((UnitOfWorkImpl) session).getCascadeDeleteObjects().contains(object)) {
            // Cascade delete does not check optimistic lock, assume ok.
            rowCount = 1;
        } else {
            rowCount = getQueryMechanism().deleteObject();
        }
        if (rowCount < 1) {
            if (session.hasEventManager()) {
                session.getEventManager().noRowsModified(this, object);
            }
        }
        if (this.usesOptimisticLocking) {
            descriptor.getOptimisticLockingPolicy().validateDelete(rowCount, object, this);
        }
        commitManager.markPostModifyCommitInProgress(getObject());
        // Verify if deep shallow modify is turned on
        if (shouldCascadeParts()) {
            descriptor.getQueryManager().postDelete(this);
        }
        if ((descriptor.getHistoryPolicy() != null) && descriptor.getHistoryPolicy().shouldHandleWrites()) {
            descriptor.getHistoryPolicy().postDelete(this);
        }
        // PERF: Avoid events if no listeners.
        if (eventManager.hasAnyEventListeners()) {
            // Need to run post-delete selector if available
            eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PostDeleteEvent, this));
        }
        if (!isUnitOfWork) {
            session.commitTransaction();
        }
        commitManager.markCommitCompleted(object);
        // CR3510313, avoid removing aggregate collections from cache (maintain cache is false).
        if (shouldMaintainCache()) {
            if (isUnitOfWork) {
                ((UnitOfWorkImpl) session).addObjectDeletedDuringCommit(object, descriptor);
            } else {
                session.getIdentityMapAccessorInstance().removeFromIdentityMap(getPrimaryKey(), descriptor.getJavaClass(), descriptor, object);
            }
        }
        return object;
    } catch (RuntimeException exception) {
        if (!isUnitOfWork) {
            session.rollbackTransaction();
        }
        commitManager.markCommitCompleted(object);
        throw exception;
    }
}
Also used : DescriptorEventManager(org.eclipse.persistence.descriptors.DescriptorEventManager) CommitManager(org.eclipse.persistence.internal.sessions.CommitManager) ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl) DescriptorEvent(org.eclipse.persistence.descriptors.DescriptorEvent) AbstractSession(org.eclipse.persistence.internal.sessions.AbstractSession)

Example 84 with UnitOfWorkImpl

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

the class DoesExistQuery method checkEarlyReturn.

/**
 * INTERNAL:
 * Check if existence can be determined without going to the database.
 * Note that custom query check is not require for does exist as the custom is always used.
 * Used by unit of work, and will return null if checkDatabaseIfInvalid is set and the cachekey is invalidated
 */
public Object checkEarlyReturn(Object object, Object primaryKey, AbstractSession session, AbstractRecord translationRow) {
    // For bug 3136413/2610803 building the selection criteria from an EJBQL string or
    // an example object is done just in time.
    buildSelectionCriteria(session);
    // Return false on null since it can't exist.  Little more done in case PK not set in the query
    if (object == null) {
        return Boolean.FALSE;
    }
    ClassDescriptor descriptor = session.getDescriptor(object.getClass());
    if (primaryKey == null) {
        primaryKey = getPrimaryKey();
        if (primaryKey == null) {
            primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(object, session, true);
        }
    }
    if (primaryKey == null) {
        return Boolean.FALSE;
    }
    // Need to do the cache check first if flag set or if we should check the cache only for existence.
    if ((shouldCheckCacheForDoesExist() || this.checkCacheFirst) && !descriptor.isDescriptorForInterface()) {
        // If this is a UOW and modification queries have been executed, the cache cannot be trusted.
        if (this.checkDatabaseIfInvalid && (session.isUnitOfWork() && ((UnitOfWorkImpl) session).shouldReadFromDB())) {
            return null;
        }
        CacheKey cacheKey;
        Class<?> objectClass = object.getClass();
        AbstractSession tempSession = session;
        if (tempSession.isUnitOfWork()) {
            cacheKey = tempSession.getIdentityMapAccessorInstance().getCacheKeyForObjectForLock(primaryKey, objectClass, descriptor);
            if (cacheKey != null) {
                // If in the UOW cache it can't be invalid.
                return Boolean.TRUE;
            }
            while (((UnitOfWorkImpl) tempSession).isNestedUnitOfWork()) {
                // could be nested lets check all UOWs
                tempSession = tempSession.getParent();
                cacheKey = tempSession.getIdentityMapAccessorInstance().getCacheKeyForObjectForLock(primaryKey, objectClass, descriptor);
                if (cacheKey != null) {
                    // If in the UOW cache it can't be invalid.
                    return Boolean.TRUE;
                }
            }
            tempSession = tempSession.getParentIdentityMapSession(descriptor, false, true);
        }
        // Did not find it registered in UOW so check main cache and check for invalidation.
        cacheKey = tempSession.getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey, objectClass, descriptor, false);
        if ((cacheKey != null)) {
            // Assume that if there is a cachekey, object exists.
            if (this.checkDatabaseIfInvalid) {
                checkDescriptor(object, session);
                if (this.descriptor.getCacheInvalidationPolicy().isInvalidated(cacheKey, System.currentTimeMillis())) {
                    return null;
                }
            }
            Object objectFromCache = cacheKey.getObject();
            if ((session.isUnitOfWork()) && ((UnitOfWorkImpl) session).wasDeleted(objectFromCache)) {
                if (shouldCheckCacheForDoesExist()) {
                    return Boolean.FALSE;
                }
            } else {
                return Boolean.TRUE;
            }
        } else if (shouldCheckCacheForDoesExist()) {
            // We know its not in cache, and a checkcache policy so return false.
            return Boolean.FALSE;
        }
    }
    // Check if we have to assume that the object does not exist.
    if (shouldAssumeNonExistenceForDoesExist()) {
        return Boolean.FALSE;
    }
    // Check to see if we only need to check that the object contains a primary key.
    if (shouldAssumeExistenceForDoesExist()) {
        return Boolean.TRUE;
    }
    return null;
}
Also used : ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl) CacheKey(org.eclipse.persistence.internal.identitymaps.CacheKey) AbstractSession(org.eclipse.persistence.internal.sessions.AbstractSession)

Example 85 with UnitOfWorkImpl

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

the class LifecycleJUnitTest method testClearWhileEntityManagerInCommitPendingStateWithClearAfterCommit.

/**
 * This test simulates EE container callbacks that could occur that affect em lifecycle state.
 * Specifically it tests whether we handle an attempt to clear an entityManager
 * that is in the middle of a commit.
 * We only clear the entityManager if we are in the states
 * (Birth == 0, WriteChangesFailed==3, Death==5 or AfterExternalTransactionRolledBack==6).
 * If we are in one of the following *Pending states we defer the clear() to the release() call later
 */
public void testClearWhileEntityManagerInCommitPendingStateWithClearAfterCommit() {
    EntityManagerFactory emf = getEntityManagerFactory();
    EntityManager em = emf.createEntityManager();
    Department dept = null;
    try {
        em.getTransaction().begin();
        dept = new Department();
        // A merge will not populate the @Id field
        // A persist will populate the @Id field
        em.persist(dept);
        // simulate an attempt to call close() while we are in the middle of a commit
        UnitOfWorkImpl uow = getUnitOfWorkFromEntityManager(em);
        // get lifecycle state
        int lifecycleBefore = uow.getLifecycle();
        assertEquals("Birth state 0 is not set ", 0, lifecycleBefore);
        em.clear();
        int lifecycleAfter = uow.getLifecycle();
        assertEquals("Birth state 0 is not set after a clear on state Birth  ", 0, lifecycleAfter);
        em.getTransaction().commit();
        // clear em
        em.clear();
        int lifecycleAfterCommit = uow.getLifecycle();
        assertEquals("Birth state 0 is not set after commit ", 0, lifecycleAfterCommit);
    } catch (RuntimeException ex) {
        if (isTransactionActive(em)) {
            rollbackTransaction(em);
        }
        closeEntityManager(em);
        throw ex;
    } finally {
        closeEntityManager(em);
    }
}
Also used : EntityManager(jakarta.persistence.EntityManager) JpaEntityManager(org.eclipse.persistence.jpa.JpaEntityManager) Department(org.eclipse.persistence.testing.models.jpa.advanced.Department) EntityManagerFactory(jakarta.persistence.EntityManagerFactory) 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