FileDocCategorySizeDatePackage
DatabaseQueryMechanism.javaAPI DocGlassfish v2 API57604Tue May 22 16:54:40 BST 2007oracle.toplink.essentials.internal.queryframework

DatabaseQueryMechanism

public abstract class DatabaseQueryMechanism extends Object implements Serializable, Cloneable

Purpose: Abstract class for all database query mechanism objects. DatabaseQueryMechanism is actually a helper class and currently is required for all types of queries. Most of the work performed by the query framework is performed in the query mechanism. The query mechanism contains the internal knowledge necessary to perform the specific database operation.

Responsibilities: Provide a common protocol for query mechanism objects. Provides all of the database specific work for the assigned query.

author
Yvon Lavoie
since
TOPLink/Java 1.0

Fields Summary
protected DatabaseQuery
query
The database query that uses this mechanism.
Constructors Summary
public DatabaseQueryMechanism()
Initialize the state of the query.

    
public DatabaseQueryMechanism(DatabaseQuery query)
Initialize the state of the query

param
query - owner of mechanism

        this.query = query;
    
Methods Summary
protected voidaddObjectDeletedDuringCommit()
Remove the query object from the identity map.

        WriteObjectQuery writeQuery = getWriteObjectQuery();
        Object object = writeQuery.getObject();

        // CR3510313, avoid removing aggregate collections from cache (maintain cache is false).
        if (writeQuery.shouldMaintainCache()) {
            if (getSession().isUnitOfWork()) {
                ((UnitOfWorkImpl)getSession()).addObjectDeletedDuringCommit(object, getDescriptor());
            } else {
                getSession().getIdentityMapAccessorInstance().removeFromIdentityMap(writeQuery.getPrimaryKey(), getDescriptor().getJavaClass(), getDescriptor());
            }
        }
    
protected voidaddWriteLockFieldForInsert()
Add the initial write lock value to the row for insert.

        if (getDescriptor().usesOptimisticLocking()) {
            getDescriptor().getOptimisticLockingPolicy().setupWriteFieldsForInsert(getWriteObjectQuery());
        }
    
public java.lang.ObjectbuildObjectsFromRows(java.util.Vector rows)
Build the objects for the rows, and answer them

exception
DatabaseException - an error has occurred on the database

        Object result = ((ReadAllQuery)getQuery()).getContainerPolicy().containerInstance(rows.size());
        return getDescriptor().getObjectBuilder().buildObjectsInto((ReadAllQuery)getQuery(), rows, result);
    
public voidbuildSelectionCriteria(oracle.toplink.essentials.internal.sessions.AbstractSession session)
Internal: In the case of EJBQL, an expression needs to be generated. Build the required expression.

        // Default is do nothing
    
public java.lang.ObjectcheckCacheForObject(oracle.toplink.essentials.internal.sessions.AbstractRecord translationRow, oracle.toplink.essentials.internal.sessions.AbstractSession session)
Perform a cache lookup for the query. If the translation row contains all the primary key fields, then a cache check will be performed. If the object is found in the cache, return it; otherwise return null.

        // Null check added for CR#4295 - TW
        if ((translationRow == null) || (translationRow.isEmpty())) {
            return null;
        }

        List keyFields = getDescriptor().getPrimaryKeyFields();
        Vector primaryKey = new Vector(keyFields.size());

        for (int index = 0; index < keyFields.size(); index++) {
            Object value = translationRow.get((DatabaseField)keyFields.get(index));
            if (value == null) {
                return null;
            } else {
                primaryKey.add(value);
            }
        }
        return session.getIdentityMapAccessorInstance().getFromIdentityMapWithDeferredLock(primaryKey, getReadObjectQuery().getReferenceClass(), false, getDescriptor());
    
protected java.lang.Objectclone()
Clone the mechanism

        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError();
        }
    
public oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanismclone(DatabaseQuery queryClone)
Clone the mechanism for the specified query clone.

        DatabaseQueryMechanism clone = (DatabaseQueryMechanism)clone();
        clone.setQuery(queryClone);
        return clone;
    
public abstract DatabaseCallcursorSelectAllRows()
Read all rows from the database using a cursored stream.

exception
DatabaseException - an error has occurred on the database

public abstract java.lang.IntegerdeleteAll()

public abstract java.lang.IntegerdeleteObject()
Delete an object This should be overriden by subclasses.

exception
DatabaseException
return
the row count.

public voiddeleteObjectForWrite()
Delete an object from the database.

        WriteObjectQuery writeQuery = getWriteObjectQuery();
        Object object = writeQuery.getObject();
        DescriptorQueryManager queryManager = getDescriptor().getQueryManager();

        // check for user-defined query
        if ((!writeQuery.isUserDefined())// this is not a user-defined query
                 &&queryManager.hasDeleteQuery()// there is a user-defined query
                 &&isExpressionQueryMechanism()) {// this is not a hand-coded call (custom SQL etc.)
            performUserDefinedDelete();
            return;
        }

        CommitManager commitManager = getSession().getCommitManager();

        // This must be done after the custom query check, otherwise it will be done twice.
        commitManager.markPreModifyCommitInProgress(object);

        if (writeQuery.getObjectChangeSet() == null) {
            // PERF: Avoid events if no listeners.
            if (getDescriptor().getEventManager().hasAnyEventListeners()) {
                // only throw the events if there is no changeset otherwise the event will be thrown twice
                // once by the calculate changes code and here
                getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PreDeleteEvent, writeQuery));
            }
        }

        // check whether deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.preDelete(writeQuery);
        }

        // In a unit of work/writeObjects the preDelete may cause a shallow update of this object,
        // in this case the following second write must do the real delete.
        if (!commitManager.isShallowCommitted(object) && !writeQuery.shouldCascadeParts()) {
            updateForeignKeyFieldBeforeDelete();
        } else {
            // CR#2660080 missing aboutToDelete event.		
            // PERF: Avoid events if no listeners.
            if (getDescriptor().getEventManager().hasAnyEventListeners()) {
                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToDeleteEvent, writeQuery);
                event.setRecord(getModifyRow());
                getDescriptor().getEventManager().executeEvent(event);
            }

            int rowCount = deleteObject().intValue();
            
            if (rowCount < 1) {
                getSession().getEventManager().noRowsModified(writeQuery, object);
            }

            if (getDescriptor().usesOptimisticLocking()) {
                getDescriptor().getOptimisticLockingPolicy().validateDelete(rowCount, object, writeQuery);
            }
                
            // remember that the object was deleted
            addObjectDeletedDuringCommit();
        }

        commitManager.markPostModifyCommitInProgress(object);
        
        // Verify if deep shallow modify is turned on.
        if (writeQuery.shouldCascadeParts()) {
            queryManager.postDelete(writeQuery);
        }

        // PERF: Avoid events if no listeners.
        if (getDescriptor().getEventManager().hasAnyEventListeners()) {
            getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostDeleteEvent, writeQuery));
        }
    
public abstract java.lang.IntegerexecuteNoSelect()
Execute a non selecting SQL call This should be overriden by subclasses.

exception
DatabaseException
return
the row count.

public abstract java.util.VectorexecuteSelect()
Execute a select SQL call and return the rows. This should be overriden by subclasses.

exception
DatabaseException

public java.lang.ObjectexecuteWrite()
Check whether the object already exists on the database; then perform an insert, update or delete, as appropriate. This method was moved here, from WriteObjectQuery.execute(), so we can hide the source. Return the object being written.

        WriteObjectQuery writeQuery = getWriteObjectQuery();
        Object object = writeQuery.getObject();
        CommitManager commitManager = getSession().getCommitManager();

        // if the object has already been committed, no work is required
        if (commitManager.isCommitCompleted(object) || commitManager.isCommitInPostModify(object)) {
            return object;
        }

        // check whether the object is already being committed -
        // if it is, then a shallow write must be executed
        if (commitManager.isCommitInPreModify(object)) {
            writeQuery.executeShallowWrite();
            return object;
        }

        try {
            getSession().beginTransaction();

            if (writeQuery.getObjectChangeSet() == null) {
                // PERF: Avoid events if no listeners.
                if (getDescriptor().getEventManager().hasAnyEventListeners()) {
                    // only throw the events if there is no changeset otherwise the event will be thrown twice
                    // once by the calculate changes code and here
                    getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PreWriteEvent, writeQuery));
                }
            }
            writeQuery.executeCommit();

            // PERF: Avoid events if no listeners.
            if (getDescriptor().getEventManager().hasAnyEventListeners()) {
                getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostWriteEvent, writeQuery));
            }

            getSession().commitTransaction();

            // notify the commit manager of the completion to the commit
            commitManager.markCommitCompleted(object);

            return object;

        } catch (RuntimeException exception) {
            getSession().rollbackTransaction();
            commitManager.markCommitCompleted(object);
            throw exception;
        }
    
public java.lang.ObjectexecuteWriteWithChangeSet()
Check whether the object already exists on the database; then perform an insert or update, as appropriate. This method was moved here, from WriteObjectQuery.execute(), so we can hide the source. Return the object being written.

        WriteObjectQuery writeQuery = getWriteObjectQuery();
        ObjectChangeSet objectChangeSet = writeQuery.getObjectChangeSet();
        CommitManager commitManager = getSession().getCommitManager();

        //if there are no changes then there is no work required
        // Check for forcedUpdate Version and Optimistic read lock (hasForcedChanges() set in ObjectChangePolicy)
        if (!objectChangeSet.hasChanges() && !objectChangeSet.hasForcedChanges()) {
            commitManager.markCommitCompleted(objectChangeSet);
            commitManager.markCommitCompleted(writeQuery.getObject());
            return writeQuery.getObject();
        }
	// if the object has already been committed, no work is required
	if (commitManager.isCommitCompleted(objectChangeSet)
			|| commitManager.isCommitInPostModify(objectChangeSet)) {
		return writeQuery.getObject();
	}

	// if the object has already been committed, no work is required
    // need to check for the object to ensure insert wasn't completed already.
	if (commitManager.isCommitCompleted(writeQuery.getObject())
			|| commitManager.isCommitInPostModify(writeQuery.getObject())) {
            return writeQuery.getObject();
        }
        try {
            getSession().beginTransaction();

            writeQuery.executeCommitWithChangeSet();

            // PERF: Avoid events if no listeners.
            if (getDescriptor().getEventManager().hasAnyEventListeners()) {
                getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostWriteEvent, writeQuery));
            }

            getSession().commitTransaction();

            // notify the commit manager of the completion to the commit
            commitManager.markCommitCompleted(objectChangeSet);
            commitManager.markCommitCompleted(writeQuery.getObject());

            return writeQuery.getObject();

        } catch (RuntimeException exception) {
            getSession().rollbackTransaction();
            commitManager.markCommitCompleted(objectChangeSet);
            commitManager.markCommitCompleted(writeQuery.getObject());
            throw exception;
        }
    
protected oracle.toplink.essentials.descriptors.ClassDescriptorgetDescriptor()
Convenience method

        return getQuery().getDescriptor();
    
public oracle.toplink.essentials.internal.sessions.AbstractRecordgetModifyRow()
Convenience method

        if (getQuery().isModifyQuery()) {
            return ((ModifyQuery)getQuery()).getModifyRow();
        } else {
            return null;
        }
    
public DatabaseQuerygetQuery()
Return the query that uses the mechanism.

        return query;
    
protected ReadObjectQuerygetReadObjectQuery()
Convenience method

        return (ReadObjectQuery)getQuery();
    
public ExpressiongetSelectionCriteria()
Return the selection criteria for the mechanism. By default this is null. This method exists because both statement and expression mechanisms use an expression and some code in the mappings depends on returning this.

        return null;
    
protected oracle.toplink.essentials.internal.sessions.AbstractSessiongetSession()
Convenience method

        return getQuery().getSession();
    
protected oracle.toplink.essentials.internal.sessions.AbstractRecordgetTranslationRow()
Convenience method

        return getQuery().getTranslationRow();
    
protected WriteObjectQuerygetWriteObjectQuery()
Convenience method

        return (WriteObjectQuery)getQuery();
    
public abstract voidinsertObject()
Insert an object.

public voidinsertObject(boolean reprepare)
Insert an object and provide the opportunity to reprepare prior to the insert. This will be overridden CR#3237

        insertObject();
    
public voidinsertObjectForWrite()
Insert an object in the database.

        WriteObjectQuery writeQuery = getWriteObjectQuery();
        Object object = writeQuery.getObject();
        DescriptorQueryManager queryManager = getDescriptor().getQueryManager();

        // check for user-defined query
        if ((!writeQuery.isUserDefined())// this is not a user-defined query
                 &&queryManager.hasInsertQuery()// there is a user-defined query
                 &&isExpressionQueryMechanism()) {// this is not a hand-coded call (custom SQL etc.)
            performUserDefinedInsert();
            return;
        }

        CommitManager commitManager = getSession().getCommitManager();

        // This must be done after the custom query check, otherwise it will be done twice.
        commitManager.markPreModifyCommitInProgress(object);

        if (writeQuery.getObjectChangeSet() == null) {
            // PERF: Avoid events if no listeners.
            if (getDescriptor().getEventManager().hasAnyEventListeners()) {
                // only throw the events if there is no changeset otherwise the event will be thrown twice
                // once by the calculate changes code and here
                getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PreInsertEvent, writeQuery));
            }
        }

        // check whether deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.preInsert(writeQuery);
        }

        // In a unit of work/writeObjects the preInsert may have caused a shallow insert of this object,
        // in this case this second write must do an update.
        if (commitManager.isShallowCommitted(object)) {
            updateForeignKeyFieldAfterInsert();
        } else {
            AbstractRecord modifyRow = writeQuery.getModifyRow();
            if (modifyRow == null) {// Maybe have been passed in as in aggregate collection.
                if (writeQuery.shouldCascadeParts()) {
                    writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRow(object, getSession()));
                } else {
                    writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowForShallowInsert(object, getSession()));
                }
            } else {
                if (writeQuery.shouldCascadeParts()) {
                    writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRow(modifyRow, object, getSession()));
                } else {
                    writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowForShallowInsert(modifyRow, object, getSession()));
                }
            }

            // the modify row and the translation row are the same for insert
            writeQuery.setTranslationRow(getModifyRow());
            if (!writeQuery.getDescriptor().isAggregateCollectionDescriptor()) {// Should/cannot be recomputed in aggregate collection.
                writeQuery.setPrimaryKey(getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, getSession()));
            }
            addWriteLockFieldForInsert();

            // CR#3237
            // Store the size of the modify row so we can determine if the user has added to the row in the insert.
            int modifyRowSize = getModifyRow().size();

            // PERF: Avoid events if no listeners.
            if (getDescriptor().getEventManager().hasAnyEventListeners()) {
                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToInsertEvent, writeQuery);
                event.setRecord(getModifyRow());
                getDescriptor().getEventManager().executeEvent(event);
            }

            // CR#3237
            // Call insert with a boolean that tells it to reprepare if the user has altered the modify row.
            insertObject(modifyRowSize != getModifyRow().size());

            // register the object before post insert to resolve possible cycles
            registerObjectInIdentityMap();
            if (writeQuery.getObjectChangeSet() != null) {
                //make sure that we put this new changeset in the changes list of the 
                //uow changeset for serialization, or customer usage.
                ((UnitOfWorkChangeSet)writeQuery.getObjectChangeSet().getUOWChangeSet()).putNewObjectInChangesList(writeQuery.getObjectChangeSet(), getSession());
            }
        }

        commitManager.markPostModifyCommitInProgress(object);
        // Verify if deep shallow modify is turned on.
        if (writeQuery.shouldCascadeParts()) {
            queryManager.postInsert(writeQuery);
        }

        // PERF: Avoid events if no listeners.
        if (getDescriptor().getEventManager().hasAnyEventListeners()) {
            getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostInsertEvent, writeQuery));
        }
    
public voidinsertObjectForWriteWithChangeSet()
Insert an object in the database.

        WriteObjectQuery writeQuery = getWriteObjectQuery();
        ObjectChangeSet objectChangeSet = writeQuery.getObjectChangeSet();
        DescriptorQueryManager queryManager = getDescriptor().getQueryManager();
        CommitManager commitManager = getSession().getCommitManager();

        // check for user-defined query
        if ((!writeQuery.isUserDefined())// this is not a user-defined query
                 &&queryManager.hasInsertQuery()// there is a user-defined query
                 &&isExpressionQueryMechanism()) {// this is not a hand-coded call (custom SQL etc.)
            //must mark the changeSet here because the userDefined Insert will not use the changesets
            commitManager.markPreModifyCommitInProgress(objectChangeSet);
            performUserDefinedInsert();
            return;
        }

        // This must be done after the custom query check, otherwise it will be done twice.
        commitManager.markPreModifyCommitInProgress(objectChangeSet);
        commitManager.markPreModifyCommitInProgress(writeQuery.getObject());

        // check whether deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.preInsert(writeQuery);
        }

        // In a unit of work/writeObjects the preInsert may have caused a shallow insert of this object,
        // in this case this second write must do an update.
        if (commitManager.isShallowCommitted(objectChangeSet)) {
            updateForeignKeyFieldAfterInsert();
        } else {
            AbstractRecord modifyRow = writeQuery.getModifyRow();
            if (modifyRow == null) {// Maybe have been passed in as in aggregate collection.
                if (writeQuery.shouldCascadeParts()) {
                    writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowWithChangeSet(objectChangeSet, getSession()));
                } else {
                    writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowForShallowInsertWithChangeSet(objectChangeSet, getSession()));
                }
            } else {
                if (writeQuery.shouldCascadeParts()) {
                    writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowWithChangeSet(modifyRow, objectChangeSet, getSession()));
                } else {
                    writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowForShallowInsertWithChangeSet(modifyRow, objectChangeSet, getSession()));
                }
            }

            // the modify row and the translation row are the same for insert
            writeQuery.setTranslationRow(getModifyRow());
            if (!writeQuery.getDescriptor().isAggregateCollectionDescriptor()) {// Should/cannot be recomputed in aggregate collection.
                writeQuery.setPrimaryKey(objectChangeSet.getPrimaryKeys());
            }
            addWriteLockFieldForInsert();

            // PERF: Avoid events if no listeners.
            if (getDescriptor().getEventManager().hasAnyEventListeners()) {
                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToInsertEvent, writeQuery);
                event.setRecord(getModifyRow());
                getDescriptor().getEventManager().executeEvent(event);
            }

            insertObject();

            // register the object before post insert to resolve possible cycles
            registerObjectInIdentityMap();
            if (objectChangeSet != null) {
                //make sure that we put this new changeset in the changes list of the 
                //uow changeset for serialization, or customer usage.
                ((UnitOfWorkChangeSet)objectChangeSet.getUOWChangeSet()).putNewObjectInChangesList(objectChangeSet, getSession());
            }
        }

        commitManager.markPostModifyCommitInProgress(objectChangeSet);
        commitManager.markPostModifyCommitInProgress(writeQuery.getObject());
        // Verify if deep shallow modify is turned on.
        if (writeQuery.shouldCascadeParts()) {
            queryManager.postInsert(writeQuery);
        }

        // PERF: Avoid events if no listeners.
        if (getDescriptor().getEventManager().hasAnyEventListeners()) {
            getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostInsertEvent, writeQuery));
        }
    
public booleanisCallQueryMechanism()
Return true if this is a call query mechanism

        return false;
    
public booleanisEJBQLCallQueryMechanism()
Delete a collection of objects This should be overriden by subclasses.

exception
DatabaseException - an error has occurred on the database

        return false;
    
public booleanisExpressionQueryMechanism()
Return true if this is an expression query mechanism

        return false;
    
public booleanisQueryByExampleMechanism()
Return true if this is a query by example mechanism

        return false;
    
public booleanisStatementQueryMechanism()
Return true if this is a statement query mechanism

        return false;
    
protected voidperformUserDefinedDelete()
Delete the object using the user defined query. This ensures that the query is cloned and prepared correctly.

        performUserDefinedWrite(getDescriptor().getQueryManager().getDeleteQuery());
    
protected voidperformUserDefinedInsert()
Insert the object using the user defined query. This ensures that the query is cloned and prepared correctly.

        performUserDefinedWrite(getDescriptor().getQueryManager().getInsertQuery());
    
protected voidperformUserDefinedUpdate()
Update the object using the user defined query. This ensures that the query is cloned and prepared correctly.

        performUserDefinedWrite(getDescriptor().getQueryManager().getUpdateQuery());
    
protected voidperformUserDefinedWrite(WriteObjectQuery userDefinedWriteQuery)
Write the object using the specified user-defined query. This ensures that the query is cloned and prepared correctly.

        userDefinedWriteQuery.checkPrepare(getSession(), getTranslationRow());

        Object object = getWriteObjectQuery().getObject();
        WriteObjectQuery writeQuery = (WriteObjectQuery)userDefinedWriteQuery.clone();
        writeQuery.setObject(object);
        writeQuery.setObjectChangeSet(getWriteObjectQuery().getObjectChangeSet());
        writeQuery.setCascadePolicy(getQuery().getCascadePolicy());
        writeQuery.setShouldMaintainCache(getQuery().shouldMaintainCache());
        writeQuery.setTranslationRow(getTranslationRow());
        writeQuery.setModifyRow(getModifyRow());
        writeQuery.setPrimaryKey(getWriteObjectQuery().getPrimaryKey());
        writeQuery.setSession(getSession());
        writeQuery.prepareForExecution();

        // HACK: If there is a changeset, the change set method must be used,
        // however it is currently broken for inserts, so until this is fixed,
        // only using correct commit for updates.
        if (getWriteObjectQuery().isUpdateObjectQuery() && (getWriteObjectQuery().getObjectChangeSet() != null)) {
            writeQuery.executeCommitWithChangeSet();
        } else {
            writeQuery.executeCommit();
        }
    
public voidprepare()
This is different from 'prepareForExecution()' in that this is called on the original query, and the other is called on the clone of the query. This query is copied for concurrency so this prepare can only setup things that will apply to any future execution of this query.

        // the default is to do nothing
    
public abstract voidprepareCursorSelectAllRows()
Pre-pare for a cursored execute. This is sent to the original query before cloning.

public abstract voidprepareDeleteAll()
Prepare for a delete all. This is sent to the original query before cloning.

public abstract voidprepareDeleteObject()
Prepare for a delete. This is sent to the original query before cloning.

public abstract voidprepareDoesExist(DatabaseField field)
Pre-pare for a select execute. This is sent to the original query before cloning.

public abstract voidprepareExecuteNoSelect()
Prepare for a raw (non-object), non-selecting call. This is sent to the original query before cloning.

public abstract voidprepareExecuteSelect()
Prepare for a raw (non-object) select call. This is sent to the original query before cloning.

public voidprepareForExecution()
All the query mechanism related things are initialized here. This method is called on the *clone* of the query with every execution.

        // the default is to do nothing
    
public abstract voidprepareInsertObject()
Prepare for an insert. This is sent to the original query before cloning.

public abstract voidprepareReportQuerySelectAllRows()
Pre-pare for a select execute. This is sent to the original query before cloning.

public abstract voidprepareReportQuerySubSelect()
Pre-pare a report query for a sub-select.

public abstract voidprepareSelectAllRows()
Prepare for a select returning (possibly) multiple rows. This is sent to the original query before cloning.

public abstract voidprepareSelectOneRow()
Prepare for a select returning a single row. This is sent to the original query before cloning.

public abstract voidprepareUpdateAll()
Prepare for an update all. This is sent to the original query before cloning.

public abstract voidprepareUpdateObject()
Prepare for an update. This is sent to the original query before cloning.

protected voidregisterObjectInIdentityMap()
Store the query object in the identity map.

        WriteObjectQuery writeQuery = getWriteObjectQuery();
        Object object = writeQuery.getObject();

        if (writeQuery.shouldMaintainCache()) {
            if (getDescriptor().usesOptimisticLocking()) {
                Object optimisticLockValue = getDescriptor().getOptimisticLockingPolicy().getValueToPutInCache(writeQuery.getModifyRow(), getSession());
                getSession().getIdentityMapAccessorInstance().putInIdentityMap(object, writeQuery.getPrimaryKey(), optimisticLockValue, System.currentTimeMillis(), getDescriptor());
            } else {
                getSession().getIdentityMapAccessorInstance().putInIdentityMap(object, writeQuery.getPrimaryKey(), null, System.currentTimeMillis(), getDescriptor());
            }
        }
    
public abstract java.util.VectorselectAllReportQueryRows()
INTERNAL: Read all rows from the database.

public abstract java.util.VectorselectAllRows()
Read and return rows from the database.

public abstract oracle.toplink.essentials.internal.sessions.AbstractRecordselectOneRow()
Read and return a row from the database.

public abstract oracle.toplink.essentials.internal.sessions.AbstractRecordselectRowForDoesExist(DatabaseField field)
Read and return a row from the database for an existence check.

public voidsetQuery(DatabaseQuery query)
Set the query that uses this mechanism.

        this.query = query;
    
public voidshallowDeleteObjectForWrite(java.lang.Object object, WriteObjectQuery writeQuery, CommitManager commitManager)
INTERNAL: Shallow delete the specified object.

        // a shallow delete must be performed
        writeQuery.dontCascadeParts();
        deleteObjectForWrite();
        // mark this object as shallow committed so that the delete will be executed
        commitManager.markShallowCommit(object);
    
public voidshallowInsertObjectForWrite(java.lang.Object object, WriteObjectQuery writeQuery, CommitManager commitManager)
INTERNAL: Shallow insert the specified object.

        // a shallow insert must be performed
        writeQuery.dontCascadeParts();
        insertObjectForWrite();
        // mark this object as shallow committed so that the insert will do an update
        commitManager.markShallowCommit(object);
    
public abstract java.lang.IntegerupdateAll()
Issue update SQL statement

public voidupdateChangeSet(oracle.toplink.essentials.descriptors.ClassDescriptor desc, ObjectChangeSet objectChangeSet, oracle.toplink.essentials.internal.sessions.AbstractRecord row, java.lang.Object object)
Update the change set with all of the field values in the row. This handle writable and read-only mappings, direct and nested aggregates. It is used from ReturningPolicy and VersionLockingPolicy.

        HashSet handledMappings = new HashSet(row.size());
        for (int i = 0; i < row.size(); i++) {
            DatabaseField field = (DatabaseField)row.getFields().elementAt(i);
            Object value = row.getValues().elementAt(i);
            updateChangeSet(desc, objectChangeSet, field, object, handledMappings);
        }
    
protected voidupdateChangeSet(oracle.toplink.essentials.descriptors.ClassDescriptor desc, ObjectChangeSet objectChangeSet, DatabaseField field, java.lang.Object object)

        updateChangeSet(desc, objectChangeSet, field, object, null);
    
protected voidupdateChangeSet(oracle.toplink.essentials.descriptors.ClassDescriptor desc, ObjectChangeSet objectChangeSet, DatabaseField field, java.lang.Object object, java.util.Collection handledMappings)

        DatabaseMapping mapping;
        Vector mappingVector = desc.getObjectBuilder().getReadOnlyMappingsForField(field);
        if (mappingVector != null) {
            for (int j = 0; j < mappingVector.size(); j++) {
                mapping = (DatabaseMapping)mappingVector.elementAt(j);
                updateChangeSet(mapping, objectChangeSet, field, object, handledMappings);
            }
        }
        mapping = desc.getObjectBuilder().getMappingForField(field);
        if (mapping != null) {
            updateChangeSet(mapping, objectChangeSet, field, object, handledMappings);
        }
    
protected voidupdateChangeSet(DatabaseMapping mapping, ObjectChangeSet objectChangeSet, DatabaseField field, java.lang.Object object, java.util.Collection handledMappings)

        if ((handledMappings != null) && handledMappings.contains(mapping)) {
            return;
        }
        if (mapping.isAggregateObjectMapping()) {
            Object aggregate = mapping.getAttributeValueFromObject(object);
            AggregateChangeRecord record = (AggregateChangeRecord)objectChangeSet.getChangesForAttributeNamed(mapping.getAttributeName());
            if (aggregate != null) {
                if (record == null) {
                    record = new AggregateChangeRecord(objectChangeSet);
                    record.setAttribute(mapping.getAttributeName());
                    record.setMapping(mapping);
                    objectChangeSet.addChange(record);
                }
                ObjectChangeSet aggregateChangeSet = (oracle.toplink.essentials.internal.sessions.ObjectChangeSet)record.getChangedObject();
                ClassDescriptor aggregateDescriptor = ((AggregateObjectMapping)mapping).getReferenceDescriptor();
                if (aggregateChangeSet == null) {
                    aggregateChangeSet = aggregateDescriptor.getObjectBuilder().createObjectChangeSet(aggregate, (oracle.toplink.essentials.internal.sessions.UnitOfWorkChangeSet)((UnitOfWorkImpl)getSession()).getUnitOfWorkChangeSet(), getSession());
                    record.setChangedObject(aggregateChangeSet);
                }
                updateChangeSet(aggregateDescriptor, aggregateChangeSet, field, aggregate, handledMappings);
            } else {
                if (record != null) {
                    record.setChangedObject(null);
                }
            }
        } else if (mapping.isDirectToFieldMapping()) {
            Object attributeValue = mapping.getAttributeValueFromObject(object);
            objectChangeSet.updateChangeRecordForAttribute(mapping, attributeValue);
        } else {
            getSession().log(SessionLog.FINEST, SessionLog.QUERY, "field_for_unsupported_mapping_returned", field, getDescriptor());
        }
    
protected voidupdateForeignKeyFieldAfterInsert()
Update the foreign key fields when resolving a bi-directonal reference in a UOW. This must always be dynamic as it is called within an insert query and is really part of the insert and does not fire update events or worry about locking.

        WriteObjectQuery writeQuery = getWriteObjectQuery();
        Object object = writeQuery.getObject();

        writeQuery.setPrimaryKey(getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, getSession()));
        // reset the translation row because the insert has occurred and the id has
        // been assigned to the object, but not the row
        writeQuery.setTranslationRow(getDescriptor().getObjectBuilder().buildRowForTranslation(object, getSession()));

        writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowForUpdate(writeQuery));
        
        updateForeignKeyFieldShallow(writeQuery);
    
protected voidupdateForeignKeyFieldBeforeDelete()
Null out the foreign key fields when resolving a bi-directonal reference in a UOW. This must always be dynamic as it is called within a delete query and is really part of the delete and does not fire update events or worry about locking.

        WriteObjectQuery writeQuery = getWriteObjectQuery();
        Object object = writeQuery.getObject();

        writeQuery.setPrimaryKey(getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, getSession()));
        // set the translation row
        writeQuery.setTranslationRow(getDescriptor().getObjectBuilder().buildRowForTranslation(object, getSession()));
        // build a query to null out the foreign keys
        writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowForShallowDelete(object, getSession()));

        updateForeignKeyFieldShallow(writeQuery);
    
protected abstract voidupdateForeignKeyFieldShallow(WriteObjectQuery writeQuery)
Update the foreign key fields when resolving a bi-directonal reference in a UOW. This must always be dynamic as it is called within an insert query and is really part of the insert and does not fire update events or worry about locking.

public abstract java.lang.IntegerupdateObject()
Update an object. Return the row count.

protected voidupdateObjectAndRowWithReturnRow(java.util.Collection returnFields, boolean isFirstCallForInsert)

        WriteObjectQuery writeQuery = getWriteObjectQuery();
        AbstractRecord outputRow = (AbstractRecord)writeQuery.getProperties().get("output");
        if ((outputRow == null) || outputRow.isEmpty()) {
            return;
        }
        AbstractRecord row = new DatabaseRecord();
        for (Iterator iterator = returnFields.iterator(); iterator.hasNext();) {
            DatabaseField field = (DatabaseField)iterator.next();
            if (outputRow.containsKey(field)) {
                row.put(field, outputRow.get(field));
            }
        }
        if (row.isEmpty()) {
            return;
        }

        Object object = writeQuery.getObject();

        getDescriptor().getObjectBuilder().assignReturnRow(object, getSession(), row);

        Vector primaryKeys = null;
        if (isFirstCallForInsert) {
            AbstractRecord pkToModify = new DatabaseRecord();
            List primaryKeyFields = getDescriptor().getPrimaryKeyFields();
            for (int i = 0; i < primaryKeyFields.size(); i++) {
                DatabaseField field = (DatabaseField)primaryKeyFields.get(i);
                if (row.containsKey(field)) {
                    pkToModify.put(field, row.get(field));
                }
            }
            if (!pkToModify.isEmpty()) {
                primaryKeys = getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, getSession());
                writeQuery.setPrimaryKey(primaryKeys);
                // Now I need to update the row
                getModifyRow().putAll(pkToModify);
                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, row, object);
                if (primaryKeys != null) {
                    objectChangeSet.setCacheKey(new CacheKey(primaryKeys));
                }
            }
        }
    
protected voidupdateObjectAndRowWithSequenceNumber()
Update the object's primary key by fetching a new sequence number from the accessor.

        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));
            }
        }
    
public voidupdateObjectForWrite()
Update the object

        WriteObjectQuery writeQuery = getWriteObjectQuery();
        Object object = writeQuery.getObject();
        DescriptorQueryManager queryManager = getDescriptor().getQueryManager();

        // check for user-defined query
        if ((!writeQuery.isUserDefined())// this is not a user-defined query
                 &&queryManager.hasUpdateQuery()// there is a user-defined query
                 &&isExpressionQueryMechanism()) {// this is not a hand-coded call (custom SQL etc.)
            performUserDefinedUpdate();
            return;
        }

        // This must be done after the custom query check, otherwise it will be done twice.
        getSession().getCommitManager().markPreModifyCommitInProgress(object);

        if (writeQuery.getObjectChangeSet() == null) {
            // PERF: Avoid events if no listeners.
            if (getDescriptor().getEventManager().hasAnyEventListeners()) {
                // only throw the events if there is no changeset otherwise the event will be thrown twice
                // once by the calculate changes code and here
                getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PreUpdateEvent, writeQuery));
            }
        }

        // Verify if deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.preUpdate(writeQuery);
        }

        // The row must not be built until after preUpdate in case the object reference has changed.
        // For a user defined update in the uow to row must be built twice to check if any update is required.
        if ((writeQuery.isUserDefined() || writeQuery.isCallQuery()) && (!getSession().isUnitOfWork())) {
            writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRow(object, getSession()));
        } else {
            writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowForUpdate(writeQuery));
        }

        if (!getModifyRow().isEmpty()) {
            // If user defined the entire row is required. Must not be built until change is known.
            if ((writeQuery.isUserDefined() || writeQuery.isCallQuery()) && getSession().isUnitOfWork()) {
                writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRow(object, getSession()));
            }

            // Update the write lock field if required
            if (getDescriptor().usesOptimisticLocking()) {
                OptimisticLockingPolicy policy = getDescriptor().getOptimisticLockingPolicy();
                policy.addLockValuesToTranslationRow(writeQuery);

                // update the row with newer lock value		
                policy.updateRowAndObjectForUpdate(writeQuery, object);               
            }

            // PERF: Avoid events if no listeners.
            if (getDescriptor().getEventManager().hasAnyEventListeners()) {
                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToUpdateEvent, writeQuery);
                event.setRecord(getModifyRow());
                getDescriptor().getEventManager().executeEvent(event);
            }

            int rowCount = updateObject().intValue();

            if (rowCount < 1) {
                getSession().getEventManager().noRowsModified(writeQuery, object);
            }
            if (getDescriptor().usesOptimisticLocking()) {
                getDescriptor().getOptimisticLockingPolicy().validateUpdate(rowCount, object, writeQuery);
            }
        }

        getSession().getCommitManager().markPostModifyCommitInProgress(object);

        // Verify if deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.postUpdate(writeQuery);
        }

        // PERF: Avoid events if no listeners.
        if (getDescriptor().getEventManager().hasAnyEventListeners()) {
            getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostUpdateEvent, writeQuery));
        }
    
public voidupdateObjectForWriteWithChangeSet()
Update the object

        WriteObjectQuery writeQuery = getWriteObjectQuery();
        Object object = writeQuery.getObject();
        DescriptorQueryManager queryManager = getDescriptor().getQueryManager();

        // check for user-defined query
        if ((!writeQuery.isUserDefined())// this is not a user-defined query
                 &&queryManager.hasUpdateQuery()// there is a user-defined query
                 &&isExpressionQueryMechanism()) {// this is not a hand-coded call (custom SQL etc.)
            // THis must be done here because the userdefined updatedoes not use a changeset so it will noe be set otherwise
            getSession().getCommitManager().markPreModifyCommitInProgress(writeQuery.getObjectChangeSet());
            performUserDefinedUpdate();
            return;
        }

        // This must be done after the custom query check, otherwise it will be done twice.
        getSession().getCommitManager().markPreModifyCommitInProgress(object);
        // This must be done after the custom query check, otherwise it will be done twice.
        getSession().getCommitManager().markPreModifyCommitInProgress(writeQuery.getObjectChangeSet());

        if (writeQuery.getObjectChangeSet().hasChanges()) {
            // PERF: Avoid events if no listeners.
            if (getDescriptor().getEventManager().hasAnyEventListeners()) {
                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.PreUpdateWithChangesEvent, writeQuery);
                getDescriptor().getEventManager().executeEvent(event);

                // PreUpdateWithChangesEvent listeners may have altered the object - should recalculate the change set.
                UnitOfWorkChangeSet uowChangeSet = (oracle.toplink.essentials.internal.sessions.UnitOfWorkChangeSet)((UnitOfWorkImpl)writeQuery.getSession()).getUnitOfWorkChangeSet();
                // writeQuery.getObjectChangeSet() is mapped to object in uowChangeSet.
                // It is first cleared then re-populated by calculateChanges method.
                writeQuery.getObjectChangeSet().clear();
                if(writeQuery.getDescriptor().getObjectChangePolicy().calculateChanges(object, ((UnitOfWorkImpl)event.getSession()).getBackupClone(object), uowChangeSet, writeQuery.getSession(), writeQuery.getDescriptor(), false) == null) {
                    // calculateChanges returns null in case the changeSet doesn't have changes.
                    // It should be removed from the list of ObjectChangeSets that have changes in uowChangeSet.
                    uowChangeSet.getAllChangeSets().remove(writeQuery.getObjectChangeSet());
                }
            }
        }
         
        // Verify if deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.preUpdate(writeQuery);
        }

        // The row must not be built until after preUpdate in case the object reference has changed.
        // For a user defined update in the uow to row must be built twice to check if any update is required.
        writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRowForUpdateWithChangeSet(writeQuery));
            
    	Boolean shouldModifyVersionField = writeQuery.getObjectChangeSet().shouldModifyVersionField();

        if (!getModifyRow().isEmpty() || (shouldModifyVersionField != null) || writeQuery.getObjectChangeSet().hasCmpPolicyForcedUpdate()) {
            // If user defined the entire row is required. Must not be built until change is known.
            if (writeQuery.isUserDefined() || writeQuery.isCallQuery()) {
                writeQuery.setModifyRow(getDescriptor().getObjectBuilder().buildRow(object, getSession()));
            }

            // Update the write lock field if required
            if (getDescriptor().usesOptimisticLocking()) {
                OptimisticLockingPolicy policy = getDescriptor().getOptimisticLockingPolicy();
                policy.addLockValuesToTranslationRow(writeQuery);

                if (!getModifyRow().isEmpty() || (shouldModifyVersionField.booleanValue() && policy instanceof VersionLockingPolicy)) {
                    // update the row with newer lock value		
                    policy.updateRowAndObjectForUpdate(writeQuery, object);
                } else if (!shouldModifyVersionField.booleanValue() && policy instanceof VersionLockingPolicy) {
                    ((VersionLockingPolicy)policy).writeLockValueIntoRow(writeQuery, object);
                }
            }

            // PERF: Avoid events if no listeners.
            if (getDescriptor().getEventManager().hasAnyEventListeners()) {
                DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToUpdateEvent, writeQuery);
                event.setRecord(getModifyRow());
                getDescriptor().getEventManager().executeEvent(event);
            }

            int rowCount = updateObject().intValue();

            if (rowCount < 1) {
                getSession().getEventManager().noRowsModified(writeQuery, object);
            }
            if (getDescriptor().usesOptimisticLocking()) {
                getDescriptor().getOptimisticLockingPolicy().validateUpdate(rowCount, object, writeQuery);
            }
        }

        getSession().getCommitManager().markPostModifyCommitInProgress(object);
        getSession().getCommitManager().markPostModifyCommitInProgress(writeQuery.getObjectChangeSet());

        // Verify if deep shallow modify is turned on
        if (writeQuery.shouldCascadeParts()) {
            queryManager.postUpdate(writeQuery);
        }

        // PERF: Avoid events if no listeners.
        if (getDescriptor().getEventManager().hasAnyEventListeners()) {
            getDescriptor().getEventManager().executeEvent(new DescriptorEvent(DescriptorEventManager.PostUpdateEvent, writeQuery));
        }