/** * Build the row representation of the object for update. The row built does not * contain entries for uninstantiated attributes. */ public AbstractRecord buildRowForShallowInsert(AbstractRecord databaseRow, Object object, AbstractSession session) { // PERF: Avoid synchronized enumerator as is concurrency bottleneck. Vector mappings = getDescriptor().getMappings(); int mappingsSize = mappings.size(); for (int index = 0; index < mappingsSize; index++) { DatabaseMapping mapping = (DatabaseMapping)mappings.get(index); mapping.writeFromObjectIntoRowForShallowInsert(object, databaseRow, session); } // If this descriptor is involved in inheritence add the class type. if (getDescriptor().hasInheritance()) { getDescriptor().getInheritancePolicy().addClassIndicatorFieldToRow(databaseRow); } // If this descriptor has multiple tables then we need to append the primary keys for // the non default tables. if (!getDescriptor().isAggregateDescriptor()) { addPrimaryKeyForNonDefaultTable(databaseRow); } return databaseRow; }
/** * INTERNAL: * Assign values from objectRow to the object through all the mappings corresponding to the field. */ public void assignReturnValueForField(Object object, ReadObjectQuery query, AbstractRecord row, DatabaseField field, Collection handledMappings) { DatabaseMapping mapping = getMappingForField(field); if (mapping != null) { assignReturnValueToMapping(object, query, row, field, mapping, handledMappings); } Vector mappingVector = getReadOnlyMappingsForField(field); if (mappingVector != null) { for (int j = 0; j < mappingVector.size(); j++) { mapping = (DatabaseMapping)mappingVector.elementAt(j); assignReturnValueToMapping(object, query, row, field, mapping, handledMappings); } } }
/** * Create a new instance, unless a workingCopyClone method is specified, then build a new instance and clone it. */ public Object buildWorkingCopyCloneFromRow(Record row, ObjectBuildingQuery query) throws DescriptorException { // For now must preserve CMP code which builds heavy clones with a context. // Also preserve for clients who use the copy policy. ObjectBuilder builder = getDescriptor().getObjectBuilder(); if (getWorkingCopyMethodName() != null) { Object original = builder.buildNewInstance(); builder.buildAttributesIntoShallowObject(original, (AbstractRecord)row, query); return buildWorkingCopyClone(original, query.getSession()); } else { return builder.buildNewInstance(); } }
/** * Build the row representation of an object. The row built is used only for translations * for the expressions in the expresion framework. */ public AbstractRecord buildRowForTranslation(Object object, AbstractSession session) { AbstractRecord databaseRow = createRecord(); for (Iterator mappings = getPrimaryKeyMappings().iterator(); mappings.hasNext();) { DatabaseMapping mapping = (DatabaseMapping)mappings.next(); if (mapping != null) { mapping.writeFromObjectIntoRow(object, databaseRow, session); } } // If this descriptor has multiple tables then we need to append the primary keys for // the non default tables, this is require for m-m, dc defined in the Builder that prefixes the wrong table name. // Ideally the mappings should take part in building the translation row so they can add required values. addPrimaryKeyForNonDefaultTable(databaseRow, object, session); return databaseRow; }
/** * Build the row representation of an object. */ public AbstractRecord buildRowForWhereClause(ObjectLevelModifyQuery query) { AbstractRecord databaseRow = createRecord(); for (Iterator mappings = getDescriptor().getMappings().iterator(); mappings.hasNext();) { DatabaseMapping mapping = (DatabaseMapping)mappings.next(); mapping.writeFromObjectIntoRowForWhereClause(query, databaseRow); } // If this descriptor has multiple tables then we need to append the primary keys for // the non default tables. if (!getDescriptor().isAggregateDescriptor()) { addPrimaryKeyForNonDefaultTable(databaseRow); } return databaseRow; }
domainObject = ((ReadObjectQuery)query).getSelectionObject(); } else { domainObject = concreteDescriptor.getObjectBuilder().buildNewInstance(); cacheKey.setObject(domainObject); copyQueryInfoToCacheKey(cacheKey, query, databaseRow, session, concreteDescriptor); concreteDescriptor.getObjectBuilder().buildAttributesIntoObject(domainObject, databaseRow, query, joinManager, false); } else { if (query.isReadObjectQuery() && ((ReadObjectQuery)query).shouldLoadResultIntoSelectionObject()) { copyInto(domainObject, ((ReadObjectQuery)query).getSelectionObject()); domainObject = ((ReadObjectQuery)query).getSelectionObject(); revertFetchGroupData(domainObject, concreteDescriptor, cacheKey, ((ObjectLevelReadQuery)query), joinManager, databaseRow, session); } else { boolean refreshRequired = true; concreteDescriptor.getObjectBuilder().buildAttributesIntoObject(domainObject, databaseRow, query, joinManager, true); cacheKey.setReadTime(query.getExecutionTime()); concreteDescriptor.getObjectBuilder().buildAttributesIntoObject(domainObject, databaseRow, query, joinManager, false); concreteDescriptor.getFetchGroupManager().unionFetchGroupIntoObject(domainObject, query.getFetchGroup()); DatabaseMapping dm = getMappingForAttributeName(qke.getName()); throw ValidationException.missingMappingForAttribute(concreteDescriptor, qke.getName(), this.toString()); } else {
DatabaseField sequenceNumberField = getDescriptor().getSequenceNumberField(); Object existingValue = getBaseValueForField(sequenceNumberField, object); AbstractRecord tempRow = createRecord(1); tempRow.put(sequenceNumberField, sequenceValue); DatabaseMapping mapping = getBaseMappingForField(sequenceNumberField); Object sequenceIntoObject = getParentObjectForField(sequenceNumberField, object);
Object workingClone = unitOfWork.getIdentityMapAccessorInstance().getIdentityMapManager().getFromIdentityMap(primaryKey, getDescriptor().getJavaClass(), getDescriptor()); CacheKey originalCacheKey = unitOfWork.getParentIdentityMapSession(query).getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey, getDescriptor().getJavaClass(), getDescriptor()); if (originalCacheKey != null) { isARefresh = wasAnOriginal && (getDescriptor().shouldAlwaysRefreshCache() || getDescriptor().getCacheInvalidationPolicy().isInvalidated(originalCacheKey, query.getExecutionTime())); workingClone = instantiateWorkingCopyClone(original, unitOfWork); workingClone = instantiateWorkingCopyCloneFromRow(databaseRow, query); unitOfWorkCacheKey = unitOfWork.getIdentityMapAccessorInstance().internalPutInIdentityMap(workingClone, primaryKey, null, 0, getDescriptor()); unitOfWorkCacheKey = unitOfWork.getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey, getDescriptor().getJavaClass(), getDescriptor()); return workingClone; copyQueryInfoToCacheKey(unitOfWorkCacheKey, query, databaseRow, unitOfWork, getDescriptor()); descriptor.getObjectChangePolicy().setChangeListener(workingClone, unitOfWork, getDescriptor()); buildAttributesIntoWorkingCopyClone(workingClone, query, joinManager, databaseRow, unitOfWork, wasAClone); Object backupClone = getDescriptor().getObjectChangePolicy().buildBackupClone(workingClone, this, unitOfWork); descriptor.getObjectChangePolicy().clearChanges(workingClone, unitOfWork, getDescriptor());
DatabaseField field = (DatabaseField)getReferenceFields().elementAt(i); if (row.containsKey(field)) { getObjectBuilder(aggregate, query.getSession()).assignReturnValueForField(aggregate, query, row, field, handledMappings); Object fieldValue = valueFromObject(targetObject, field, query.getSession()); if (fieldValue == null) { Object baseValue = getDescriptor().getObjectBuilder().getBaseValueForField(field, targetObject); if (baseValue != null) { DatabaseMapping baseMapping = getDescriptor().getObjectBuilder().getBaseMappingForField(field); if (baseMapping.isForeignReferenceMapping()) { ForeignReferenceMapping refMapping = (ForeignReferenceMapping)baseMapping;
aggregate = descriptor.getObjectBuilder().buildNewInstance(); refreshing = false; aggregate = descriptor.getObjectBuilder().buildNewInstance(); refreshing = false; descriptor.getObjectBuilder().buildAttributesIntoShallowObject(aggregate, databaseRow, nestedQuery); } else if (session.isUnitOfWork()) { descriptor.getObjectBuilder().buildAttributesIntoWorkingCopyClone(aggregate, nestedQuery, joinManager, databaseRow, (UnitOfWorkImpl)session, refreshing); } else { descriptor.getObjectBuilder().buildAttributesIntoObject(aggregate, databaseRow, nestedQuery, joinManager, refreshing);
/** * ADVANCED: * Assign sequence number to the object. * This allows for an object's id to be assigned before commit. * It can be used if the application requires to use the object id before the object exists on the database. * Normally all ids are assigned during the commit automatically. */ public void assignSequenceNumber(Object object) throws DatabaseException { //** sequencing refactoring startOperationProfile(SessionProfiler.AssignSequence); try { ObjectBuilder builder = getDescriptor(object).getObjectBuilder(); // This is done outside of a transaction to ensure optimial concurrency and deadlock avoidance in the sequence table. if (builder.getDescriptor().usesSequenceNumbers() && !getSequencing().shouldAcquireValueAfterInsert(object.getClass())) { Object implementation = builder.unwrapObject(object, this); builder.assignSequenceNumber(implementation, this); } } catch (RuntimeException exception) { handleException(exception); } endOperationProfile(SessionProfiler.AssignSequence); }
getDescriptor().getObjectBuilder().assignReturnRow(object, getSession(), row); primaryKeys = getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, getSession()); writeQuery.setPrimaryKey(primaryKeys); getDescriptor().getObjectBuilder().addPrimaryKeyForNonDefaultTable(getModifyRow());
/** * Update the object's primary key by fetching a new sequence number from the accessor. */ protected void updateObjectAndRowWithSequenceNumber() throws DatabaseException { WriteObjectQuery writeQuery = getWriteObjectQuery(); Object object = writeQuery.getObject(); Object sequenceValue = getDescriptor().getObjectBuilder().assignSequenceNumber(object, getSession()); if (sequenceValue == null) { return; } Vector primaryKeys = getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, getSession()); writeQuery.setPrimaryKey(primaryKeys); DatabaseField sequenceNumberField = getDescriptor().getSequenceNumberField(); // Now I need to update the row getModifyRow().put(sequenceNumberField, sequenceValue); getDescriptor().getObjectBuilder().addPrimaryKeyForNonDefaultTable(getModifyRow()); // update the changeSet if there is one if (getSession().isUnitOfWork()) { ObjectChangeSet objectChangeSet = writeQuery.getObjectChangeSet(); if ((objectChangeSet == null) && (((UnitOfWorkImpl)getSession()).getUnitOfWorkChangeSet() != null)) { objectChangeSet = (ObjectChangeSet)((UnitOfWorkImpl)getSession()).getUnitOfWorkChangeSet().getObjectChangeSetForClone(object); } if (objectChangeSet != null) { updateChangeSet(getDescriptor(), objectChangeSet, sequenceNumberField, object); objectChangeSet.setCacheKey(new CacheKey(primaryKeys)); } } }
/** * INTERNAL: * retrieves the lock value from the object. */ protected Object lockValueFromObject(Object domainObject) { return getDescriptor().getObjectBuilder().getBaseValueForField(getWriteLockField(), domainObject); }
/** * INTERNAL: * Update the row, object and change set with the version value. * This handles the version being mapped in nested aggregates, writable or read-only. */ protected void updateWriteLockValueForWrite(ObjectLevelModifyQuery query, Object lockValue) { query.getModifyRow().put(getWriteLockField(), lockValue); ObjectChangeSet objectChangeSet = query.getObjectChangeSet(); if (objectChangeSet != null) { objectChangeSet.setWriteLockValue(lockValue); } // CR#3173211 // If the value is stored in the cache or object, there still may // be read-only mappings for it, so the object must always be updated for // any writable or read-only mappings for the version value. // Reuse the method used for returning as has the same requirements. AbstractRecord record = getDescriptor().getObjectBuilder().createRecord(1); record.put(getWriteLockField(), lockValue); getDescriptor().getObjectBuilder().assignReturnRow(query.getObject(), query.getSession(), record); if (query.getSession().isUnitOfWork() && (((UnitOfWorkImpl)query.getSession()).getUnitOfWorkChangeSet() != null)) { if (objectChangeSet == null) { // For aggregate collections the change set may be null, as they use the old commit still. objectChangeSet = (ObjectChangeSet)((UnitOfWorkImpl)query.getSession()).getUnitOfWorkChangeSet().getObjectChangeSetForClone(query.getObject()); } query.getQueryMechanism().updateChangeSet(getDescriptor(), objectChangeSet, record, query.getObject()); } }
/** * Add the primary key and its value to the databaseRow for all the non default tables. * This method is used while writing into the multiple tables. */ public void addPrimaryKeyForNonDefaultTable(AbstractRecord databaseRow) { // this method has been revised so it calls addPrimaryKeyForNonDefaultTable(DatabaseRow, Object, Session) is similar. // the session and object are null in this case. addPrimaryKeyForNonDefaultTable(databaseRow, null, null); }
/** * INTERNAL: * Assign returned row to object */ public void assignReturnRow(Object object, AbstractSession writeSession, AbstractRecord row) throws DatabaseException { writeSession.log(SessionLog.FINEST, SessionLog.QUERY, "assign_return_row", row); // Require a query context to read into an object. ReadObjectQuery query = new ReadObjectQuery(); query.setSession(writeSession); // To avoid processing the same mapping twice, // maintain Collection of mappings already used. HashSet handledMappings = new HashSet(row.size()); for (int index = 0; index < row.size(); index++) { DatabaseField field = (DatabaseField)row.getFields().elementAt(index); assignReturnValueForField(object, query, row, field, handledMappings); } }
Object object = unregisteredNewObjectsEnum.nextElement(); if (getDescriptor(object).usesSequenceNumbers() && ((!isObjectRegistered(object)) || isCloneNewObject(object)) && (shouldAcquireValueBeforeInsertForAll || !sequencing.shouldAcquireValueAfterInsert(object.getClass()))) { getDescriptor(object).getObjectBuilder().assignSequenceNumber(object, this); Object object = registeredNewObjectsEnum.nextElement(); if (getDescriptor(object).usesSequenceNumbers() && ((!isObjectRegistered(object)) || isCloneNewObject(object)) && (shouldAcquireValueBeforeInsertForAll || !sequencing.shouldAcquireValueAfterInsert(object.getClass()))) { getDescriptor(object).getObjectBuilder().assignSequenceNumber(object, this);
this.objectBuilder = new ObjectBuilder(this); setCopyPolicy(new InstantiationCopyPolicy()); setInstantiationPolicy(new InstantiationPolicy());
/** * Clean up the cached object data and only revert the fetch group data back to the cached object. */ private void revertFetchGroupData(Object domainObject, ClassDescriptor concreteDescriptor, CacheKey cacheKey, ObjectBuildingQuery query, JoinedAttributeManager joinManager, AbstractRecord databaseRow, AbstractSession session) { //the cached object is either invalidated, or staled as the version is newer, or a refresh is explicitly set on the query. //clean all data of the cache object. concreteDescriptor.getFetchGroupManager().reset(domainObject); //read in the fetch group data only concreteDescriptor.getObjectBuilder().buildAttributesIntoObject(domainObject, databaseRow, query, joinManager, false); //set fetch group refrence to the cached object concreteDescriptor.getFetchGroupManager().setObjectFetchGroup(domainObject, query.getFetchGroup()); //set refresh on fetch group concreteDescriptor.getFetchGroupManager().setRefreshOnFetchGroupToObject(domainObject, (query.shouldRefreshIdentityMapResult() || concreteDescriptor.shouldAlwaysRefreshCache())); //set query id to prevent infinite recursion on refresh object cascade all cacheKey.setLastUpdatedQueryId(query.getQueryId()); //register the object into the IM and set the write lock object if applied. if (concreteDescriptor.usesOptimisticLocking()) { OptimisticLockingPolicy policy = concreteDescriptor.getOptimisticLockingPolicy(); cacheKey.setWriteLockValue(policy.getValueToPutInCache(databaseRow, session)); } cacheKey.setReadTime(query.getExecutionTime()); //validate the cached object cacheKey.setInvalidationState(CacheKey.CHECK_INVALIDATION_POLICY); }