Search in sources :

Example 21 with UnitOfWorkImpl

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

the class ObjectBuilder method buildObjectFromResultSetInternal.

/**
 * INTERNAL:
 * Builds a working copy clone directly from a result set.
 * PERF: This method is optimized for a specific case of building objects
 * so can avoid many of the normal checks, only queries that have this criteria
 * can use this method of building objects.
 */
private Object buildObjectFromResultSetInternal(ObjectBuildingQuery query, JoinedAttributeManager joinManager, ResultSet resultSet, AbstractSession executionSession, DatabaseAccessor accessor, ResultSetMetaData metaData, DatabasePlatform platform, Vector fieldsList, DatabaseField[] fieldsArray) throws SQLException {
    ClassDescriptor descriptor = this.descriptor;
    int pkFieldsSize = descriptor.getPrimaryKeyFields().size();
    DatabaseMapping primaryKeyMapping = null;
    AbstractRecord row = null;
    Object[] values = null;
    Object primaryKey;
    if (isSimple && pkFieldsSize == 1) {
        primaryKeyMapping = this.primaryKeyMappings.get(0);
        primaryKey = primaryKeyMapping.valueFromResultSet(resultSet, query, executionSession, accessor, metaData, 1, platform);
    } else {
        values = new Object[fieldsArray.length];
        row = new ArrayRecord(fieldsList, fieldsArray, values);
        accessor.populateRow(fieldsArray, values, resultSet, metaData, executionSession, 0, pkFieldsSize);
        primaryKey = extractPrimaryKeyFromRow(row, executionSession);
    }
    UnitOfWorkImpl unitOfWork = null;
    AbstractSession session = executionSession;
    boolean isolated = !descriptor.getCachePolicy().isSharedIsolation();
    if (session.isUnitOfWork()) {
        unitOfWork = (UnitOfWorkImpl) executionSession;
        isolated |= unitOfWork.wasTransactionBegunPrematurely() && descriptor.shouldIsolateObjectsInUnitOfWorkEarlyTransaction();
    }
    CacheKey cacheKey = session.getIdentityMapAccessorInstance().getIdentityMapManager().acquireLock(primaryKey, descriptor.getJavaClass(), false, descriptor, query.isCacheCheckComplete());
    CacheKey cacheKeyToUse = cacheKey;
    CacheKey parentCacheKey = null;
    Object object = cacheKey.getObject();
    try {
        // Found locally in the unit of work, or session query and found in the session.
        if (object != null) {
            return object;
        }
        if ((unitOfWork != null) && !isolated) {
            // Need to lookup in the session.
            session = unitOfWork.getParentIdentityMapSession(query);
            parentCacheKey = session.getIdentityMapAccessorInstance().getIdentityMapManager().acquireLock(primaryKey, descriptor.getJavaClass(), false, descriptor, query.isCacheCheckComplete());
            cacheKeyToUse = parentCacheKey;
            object = parentCacheKey.getObject();
        }
        // If the object is not in the cache, it needs to be built, this is building in the unit of work if isolated.
        if (object == null) {
            object = buildNewInstance();
            if (unitOfWork == null) {
                cacheKey.setObject(object);
            } else {
                if (isolated) {
                    cacheKey.setObject(object);
                    unitOfWork.getCloneMapping().put(object, object);
                } else {
                    parentCacheKey.setObject(object);
                }
            }
            List<DatabaseMapping> mappings = descriptor.getMappings();
            int size = mappings.size();
            if (isSimple) {
                int shift = descriptor.getTables().size() * pkFieldsSize;
                if (primaryKeyMapping != null) {
                    // simple primary key - set pk directly through the mapping
                    primaryKeyMapping.setAttributeValueInObject(object, primaryKey);
                } else {
                    // composite primary key - set pk using pkRow
                    boolean isTargetProtected = session.isProtectedSession();
                    for (int index = 0; index < pkFieldsSize; index++) {
                        DatabaseMapping mapping = mappings.get(index);
                        mapping.readFromRowIntoObject(row, joinManager, object, cacheKeyToUse, query, session, isTargetProtected);
                    }
                }
                // set the rest using mappings directly
                for (int index = pkFieldsSize; index < size; index++) {
                    DatabaseMapping mapping = mappings.get(index);
                    mapping.readFromResultSetIntoObject(resultSet, object, query, session, accessor, metaData, index + shift, platform);
                }
            } else {
                boolean isTargetProtected = session.isProtectedSession();
                accessor.populateRow(fieldsArray, values, resultSet, metaData, session, pkFieldsSize, fieldsArray.length);
                for (int index = 0; index < size; index++) {
                    DatabaseMapping mapping = mappings.get(index);
                    mapping.readFromRowIntoObject(row, joinManager, object, cacheKeyToUse, query, session, isTargetProtected);
                }
            }
            ((PersistenceEntity) object)._persistence_setId(primaryKey);
            if ((unitOfWork != null) && isolated) {
                ObjectChangePolicy policy = descriptor.getObjectChangePolicy();
                policy.setChangeListener(object, unitOfWork, descriptor);
            }
        }
        if ((unitOfWork != null) && !isolated) {
            // Need to clone the object in the unit of work.
            // TODO: Doesn't work all the time
            // With one setup (jpa2.performance tests) produces a shallow clone (which is good enough for isSimple==true case only),
            // in other (jpa.advanced tests) - just a brand new empty object.
            Object clone = instantiateWorkingCopyClone(object, unitOfWork);
            ((PersistenceEntity) clone)._persistence_setId(cacheKey.getKey());
            unitOfWork.getCloneMapping().put(clone, clone);
            unitOfWork.getCloneToOriginals().put(clone, object);
            cacheKey.setObject(clone);
            ObjectChangePolicy policy = descriptor.getObjectChangePolicy();
            policy.setChangeListener(clone, unitOfWork, descriptor);
            object = clone;
        }
    } finally {
        cacheKey.release();
        if (parentCacheKey != null) {
            parentCacheKey.release();
        }
    }
    return object;
}
Also used : ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) ArrayRecord(org.eclipse.persistence.internal.sessions.ArrayRecord) AbstractRecord(org.eclipse.persistence.internal.sessions.AbstractRecord) ObjectChangePolicy(org.eclipse.persistence.descriptors.changetracking.ObjectChangePolicy) UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl) DatabaseMapping(org.eclipse.persistence.mappings.DatabaseMapping) InvalidObject(org.eclipse.persistence.internal.helper.InvalidObject) CacheKey(org.eclipse.persistence.internal.identitymaps.CacheKey) AbstractSession(org.eclipse.persistence.internal.sessions.AbstractSession)

Example 22 with UnitOfWorkImpl

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

the class ObjectReferenceMapping method update.

/**
 * INTERNAL:
 * Update the private owned part.
 */
protected void update(WriteObjectQuery query) throws DatabaseException, OptimisticLockException {
    if (!shouldObjectModifyCascadeToParts(query)) {
        return;
    }
    Object sourceObject = query.getObject();
    Object attributeValue = getAttributeValueFromObject(sourceObject);
    // If objects are not instantiated that means they are not changed.
    if (!this.indirectionPolicy.objectIsInstantiated(attributeValue)) {
        return;
    }
    // Get the privately owned parts in the memory
    AbstractSession session = query.getSession();
    Object object = getRealAttributeValueFromAttribute(attributeValue, sourceObject, session);
    if (object != null) {
        ObjectChangeSet changeSet = query.getObjectChangeSet();
        if (changeSet != null) {
            ObjectReferenceChangeRecord changeRecord = (ObjectReferenceChangeRecord) query.getObjectChangeSet().getChangesForAttributeNamed(getAttributeName());
            if (changeRecord != null) {
                changeSet = (ObjectChangeSet) changeRecord.getNewValue();
                // PERF: If it is not new, then cascading is not required.
                if (!changeSet.isNew()) {
                    return;
                }
            } else {
                // no changeRecord no change to reference.
                return;
            }
        } else {
            UnitOfWorkChangeSet uowChangeSet = null;
            // Get changeSet for referenced object.
            if (session.isUnitOfWork() && (((UnitOfWorkImpl) session).getUnitOfWorkChangeSet() != null)) {
                uowChangeSet = (UnitOfWorkChangeSet) ((UnitOfWorkImpl) session).getUnitOfWorkChangeSet();
                changeSet = (ObjectChangeSet) uowChangeSet.getObjectChangeSetForClone(object);
                // PERF: If the changeSet is null it must be existing, if it is not new, then cascading is not required.
                if (changeSet == null || !changeSet.isNew()) {
                    return;
                }
            }
        }
        // PERF: Only write dependent object if they are new.
        if ((!query.shouldCascadeOnlyDependentParts()) || (changeSet == null) || changeSet.isNew()) {
            // PERF: Avoid query execution if already written.
            if (session.getCommitManager().isCommitCompletedInPostOrIgnore(object)) {
                return;
            }
            WriteObjectQuery writeQuery = new WriteObjectQuery();
            writeQuery.setIsExecutionClone(true);
            writeQuery.setObject(object);
            writeQuery.setObjectChangeSet(changeSet);
            writeQuery.setCascadePolicy(query.getCascadePolicy());
            session.executeQuery(writeQuery);
        }
    }
}
Also used : ObjectReferenceChangeRecord(org.eclipse.persistence.internal.sessions.ObjectReferenceChangeRecord) WriteObjectQuery(org.eclipse.persistence.queries.WriteObjectQuery) UnitOfWorkChangeSet(org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet) ObjectChangeSet(org.eclipse.persistence.internal.sessions.ObjectChangeSet) UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl) AbstractSession(org.eclipse.persistence.internal.sessions.AbstractSession)

Example 23 with UnitOfWorkImpl

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

the class ObjectReferenceMapping method earlyPreDelete.

/**
 * INTERNAL:
 * Record deletion dependencies for foreign key constraints.
 * This is used during deletion to resolve deletion cycles.
 */
@Override
public void earlyPreDelete(DeleteObjectQuery query, Object object) {
    AbstractSession session = query.getSession();
    // Avoid instantiating objects.
    Object attributeValue = getAttributeValueFromObject(object);
    Object targetObject = null;
    if (!this.indirectionPolicy.objectIsInstantiated(attributeValue) && !this.indirectionPolicy.objectIsEasilyInstantiated(attributeValue)) {
        AbstractRecord referenceRow = this.indirectionPolicy.extractReferenceRow(attributeValue);
        targetObject = this.selectionQuery.checkEarlyReturn(session, referenceRow);
    } else {
        targetObject = getRealAttributeValueFromAttribute(attributeValue, object, session);
    }
    UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl) session;
    if ((targetObject != null) && unitOfWork.getDeletedObjects().containsKey(targetObject)) {
        unitOfWork.addDeletionDependency(targetObject, object);
    }
}
Also used : AbstractRecord(org.eclipse.persistence.internal.sessions.AbstractRecord) UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl) AbstractSession(org.eclipse.persistence.internal.sessions.AbstractSession)

Example 24 with UnitOfWorkImpl

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

the class QueryKeyExpression method valuesFromCollection.

/**
 * INTERNAL
 * This method iterates through a collection and gets the values from the objects to conform in an in-memory query.
 */
public Object valuesFromCollection(Object object, AbstractSession session, int valueHolderPolicy, boolean isObjectUnregistered) {
    // in case the mapping is null - this can happen if a query key is being used
    // In this case, check for the query key and find it's mapping.
    boolean readMappingFromQueryKey = false;
    if (getMapping() == null) {
        getMappingFromQueryKey();
        readMappingFromQueryKey = true;
    }
    // For bug 2780817 get the mapping directly from the object.  In EJB 2.0
    // inheritance, each child must override mappings defined in an abstract
    // class with its own.
    DatabaseMapping mapping = this.mapping;
    ClassDescriptor descriptor = mapping.getDescriptor();
    if (descriptor.hasInheritance() && (descriptor.getJavaClass() != object.getClass())) {
        descriptor = descriptor.getInheritancePolicy().getDescriptor(object.getClass());
        mapping = descriptor.getObjectBuilder().getMappingForAttributeName(mapping.getAttributeName());
    }
    // fetch group support
    if (descriptor.hasFetchGroupManager()) {
        FetchGroupManager fetchGroupManager = descriptor.getFetchGroupManager();
        if (fetchGroupManager.isPartialObject(object) && (!fetchGroupManager.isAttributeFetched(object, mapping.getAttributeName()))) {
            // the conforming attribute is not fetched, simply throw exception
            throw QueryException.cannotConformUnfetchedAttribute(mapping.getAttributeName());
        }
    }
    if (mapping.isAbstractColumnMapping()) {
        return mapping.valueFromObject(object, mapping.getField(), session);
    } else if (mapping.isForeignReferenceMapping()) {
        // CR 3677 integration of a ValueHolderPolicy
        Object valueFromMapping = mapping.getAttributeValueFromObject(object);
        if (!((ForeignReferenceMapping) mapping).getIndirectionPolicy().objectIsInstantiated(valueFromMapping)) {
            if (valueHolderPolicy != InMemoryQueryIndirectionPolicy.SHOULD_TRIGGER_INDIRECTION) {
                // you should instantiate the valueholder for this to work
                throw QueryException.mustInstantiateValueholders();
            }
        // maybe we should throw this exception from the start, to save time
        }
        Object valueToIterate = mapping.getRealAttributeValueFromObject(object, session);
        UnitOfWorkImpl uow = isObjectUnregistered ? (UnitOfWorkImpl) session : null;
        // }
        if (mapping.isCollectionMapping() && (valueToIterate != null)) {
            // For bug 2766379 must use the correct version of vectorFor to
            // unwrap the result same time.
            valueToIterate = mapping.getContainerPolicy().vectorFor(valueToIterate, session);
            // registered objects.
            if (isObjectUnregistered && (uow.getCloneMapping().get(object) == null)) {
                Vector objectValues = (Vector) valueToIterate;
                for (int i = 0; i < objectValues.size(); i++) {
                    Object original = objectValues.elementAt(i);
                    Object clone = uow.getIdentityMapAccessorInstance().getIdentityMapManager().getFromIdentityMap(original);
                    if (clone != null) {
                        objectValues.setElementAt(clone, i);
                    }
                }
            }
        // For CR 2612601, conforming without registering, a query could be
        // bob.get("address").get("city").equal("Ottawa"); where the address
        // has been registered and modified in the UOW, but bob has not.  Thus
        // even though bob does not point to the modified address now, it will
        // as soon as it is registered, so should point to it here.
        } else if (isObjectUnregistered && (uow.getCloneMapping().get(object) == null)) {
            Object clone = uow.getIdentityMapAccessorInstance().getIdentityMapManager().getFromIdentityMap(valueToIterate);
            if (clone != null) {
                valueToIterate = clone;
            }
        }
        return valueToIterate;
    } else if (mapping.isAggregateMapping()) {
        Object aggregateValue = mapping.getAttributeValueFromObject(object);
        // Bug 3995468 - if this query key is to a mapping in an aggregate object, get the object from actual mapping rather than the aggregate mapping
        while (readMappingFromQueryKey && mapping.isAggregateObjectMapping() && !((AggregateObjectMapping) mapping).getReferenceClass().equals(queryKey.getDescriptor().getJavaClass())) {
            mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(((DirectQueryKey) queryKey).getField());
            aggregateValue = mapping.getRealAttributeValueFromObject(aggregateValue, session);
        }
        return aggregateValue;
    } else {
        throw QueryException.cannotConformExpression();
    }
}
Also used : FetchGroupManager(org.eclipse.persistence.descriptors.FetchGroupManager) ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) DirectQueryKey(org.eclipse.persistence.mappings.querykeys.DirectQueryKey) UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl) DatabaseMapping(org.eclipse.persistence.mappings.DatabaseMapping) Vector(java.util.Vector)

Example 25 with UnitOfWorkImpl

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

the class AggregateObjectMapping method getTargetVersionOfSourceObject.

/**
 * INTERNAL:
 * If required, get the targetVersion of the source object from the merge manager.
 *
 * Used with MapKeyContainerPolicy to abstract getting the target version of a source key
 */
@Override
public Object getTargetVersionOfSourceObject(Object object, Object parent, MergeManager mergeManager, AbstractSession targetSession) {
    if (mergeManager.getSession().isUnitOfWork()) {
        UnitOfWorkImpl uow = (UnitOfWorkImpl) mergeManager.getSession();
        Object aggregateObject = buildClonePart(object, parent, null, null, targetSession, uow.isOriginalNewObject(parent));
        return aggregateObject;
    }
    return object;
}
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