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;
}
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);
}
}
}
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);
}
}
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();
}
}
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;
}
Aggregations