FileDocCategorySizeDatePackage
DoesExistQuery.javaAPI DocGlassfish v2 API16714Thu Jul 19 11:52:00 BST 2007oracle.toplink.essentials.queryframework

DoesExistQuery

public class DoesExistQuery extends DatabaseQuery

Purpose: This should only be used by the descriptor, this should not be executed directly. Used to determine if an object resides on the database. DoesExistQuery is normally used to determine whether to make an update or insert statement when writing an object.

Responsibilities: Verify the existence of an object. Used only by a write object query.

author
Yvon Lavoie
since
TOPLink/Java 1.0

Fields Summary
public static final int
AssumeNonExistence
public static final int
AssumeExistence
public static final int
CheckCache
public static final int
CheckDatabase
protected Vector
primaryKey
Query that is performing the does exist check.
protected Object
object
protected int
existencePolicy
Flag to determine existence check policy.
protected boolean
checkDatabaseIfInvalid
Flag to determine cache invalidation policy support. This overrides checkcache existence settings if the object is set to be invalid or if the cache cannot be trusted
public boolean
checkCacheFirst
Flag to get checkearlyreturn to override assume(non)existence and database checks with a cache check
Constructors Summary
public DoesExistQuery()
PUBLIC: Initialize the state of the query . By default the cache is checked, if non cache is used the descriptor should throw a exception and validate.

//default to false, set in uow to true

                                    
      
        this.existencePolicy = CheckCache;
        this.checkDatabaseIfInvalid = true;
        this.checkCacheFirst = false;
    
public DoesExistQuery(Object object)
PUBLIC: Create a query to check if the object exists.

        this();
        this.object = object;
    
public DoesExistQuery(Call call)
PUBLIC: Create a query to check if the object exists.

        this();
        setCall(call);
    
Methods Summary
public voidassumeExistenceForDoesExist()
PUBLIC: Assume that if the objects primary key does not include null then it must exist. This may be used if the user's system garentees that an object with non-null key exists.

        setExistencePolicy(AssumeExistence);
    
public voidassumeNonExistenceForDoesExist()
PUBLIC: Assume that the object does not exist. This may be used if the user's system garentees objects must always be inserted.

        setExistencePolicy(AssumeNonExistence);
    
public voidcheckCacheForDoesExist()
PUBLIC: Assume that if the objects primary key does not include null and it is in the cache, then is must exist. This should only be used if a full identity map is being used, and a new object in the client cannot have been inserted by another client.

        setExistencePolicy(CheckCache);
    
public voidcheckDatabaseForDoesExist()
PUBLIC: Perform does exist check on the database through slecting the primary key.

        setExistencePolicy(CheckDatabase);
    
public java.lang.ObjectcheckEarlyReturn(java.lang.Object object, java.util.Vector primaryKey, oracle.toplink.essentials.internal.sessions.AbstractSession session, oracle.toplink.essentials.internal.sessions.AbstractRecord translationRow)
INTERNAL: Check if existence can be determined without going to the database. Note that custom query check is not require for does exist as the custom is always used. Used by unit of work, and will return null if checkDatabaseIfInvalid is set and the cachekey is invalidated

        // For bug 3136413/2610803 building the selection criteria from an EJBQL string or
        // an example object is done just in time.
        buildSelectionCriteria(session);
        
        // Return false on null since it can't exist.  Little more done incase PK not set in the query
        if  (object == null){ 
            return Boolean.FALSE;
        }
        ClassDescriptor descriptor = session.getDescriptor(object.getClass());
        if (primaryKey == null) {
            primaryKey = this.getPrimaryKey();
            if ( primaryKey == null ){
                primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(object, session);
            }
                
        }
        if ((primaryKey == null)|| (primaryKey.contains(null)) ) {
            return Boolean.FALSE;
        }
        
        //need to do the cache check first if flag set or if we should check the cache only for existence
        if (shouldCheckCacheForDoesExist() ||(checkCacheFirst)) {
        
            //if this is a UOW and modification queries have been executed, the cache cannot be trusted
            if ( checkDatabaseIfInvalid && (session.isUnitOfWork() && 
                    ((UnitOfWorkImpl)session).shouldReadFromDB() ) ){
                return null;
            }
                
            oracle.toplink.essentials.internal.identitymaps.CacheKey cacheKey;
            Class objectClass = object.getClass();
            if (session.isUnitOfWork()){
                cacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey,objectClass, descriptor);
                if (cacheKey!=null){ //if in the UOW cache, it exists and can't be invalid
                    return Boolean.TRUE;
                }
                cacheKey = ((UnitOfWorkImpl)session).getParent().getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey,objectClass, descriptor);
            }else{
                cacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey,objectClass, descriptor);
            }
                
            if ((cacheKey !=null)){
                //assume that if there is a cachekey, object exists
                boolean invalid;
                if ( checkDatabaseIfInvalid ){
                    long currentTimeInMillis = System.currentTimeMillis();
                    invalid = session.getDescriptor(objectClass).getCacheInvalidationPolicy().isInvalidated(cacheKey, currentTimeInMillis);
                }else {
                    invalid = false;
                }
                
                if (!invalid){
                    Object objectFromCache = cacheKey.getObject();
                    if ((session instanceof oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork)&&
                            (((oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork)session).getUnregisteredDeletedCloneForOriginal(objectFromCache)!=null)){
                  //session.isUnitOfWork() && objectFromCache!=null && ((UnitOfWorkImpl)session).isObjectDeleted(objectFromCache)){
                        if(shouldCheckCacheForDoesExist()){
                            return Boolean.FALSE;
                        }
                    }else {
                        return Boolean.TRUE;
                    }
                    
                }else {
                    //We know it is invalid, and checkDatabaseIfInvalid policy so skip to the database
                    return null;
                }
            }else if(shouldCheckCacheForDoesExist()){
                //We know its not in cache, and a checkcache policy so return false
                return Boolean.FALSE;
            }
        }
        // Check if we have to assume that the object does not exist.
        if (shouldAssumeNonExistenceForDoesExist()) {
            return Boolean.FALSE;
        }

        // Check to see if we only need to check that the object contains a primary key.
        if (shouldAssumeExistenceForDoesExist()) {
            return Boolean.TRUE;
        }

        return null;
    
public java.lang.ObjectcheckEarlyReturn(oracle.toplink.essentials.internal.sessions.AbstractSession session, oracle.toplink.essentials.internal.sessions.AbstractRecord translationRow)
INTERNAL: Check if existence can be determined without going to the database. Note that custom query check is not require for does exist as the custom is always used.

        return checkEarlyReturn(getObject(), getPrimaryKey(), session, translationRow);
    
public java.lang.ObjectexecuteDatabaseQuery()
INTERNAL: Return if the object exists on the database. This must be a Boolean object to conform with returning an object. If using optimistic locking, check that the value matches.

exception
DatabaseException - an error has occurred on the database.

        // Get the required fields for does exist check.
        DatabaseField field = getDoesExistField();

        // Get row from database
        AbstractRecord databaseRow = getQueryMechanism().selectRowForDoesExist(field);

        // Null means no row was returned.
        return new Boolean(databaseRow != null);
    
public booleangetCheckCacheFirst()
INTERNAL:

param
checkCacheFirst

        return this.checkCacheFirst;
    
public booleangetCheckDatabaseIfInvalid()
INTERNAL:

param
checkDatabaseIfInvalid

        return this.checkCacheFirst;
    
protected DatabaseFieldgetDoesExistField()
INTERNAL: Return the write lock field or the first primary key field if not using locking.

        return (DatabaseField)(getDescriptor().getPrimaryKeyFields().get(0));
    
public intgetExistencePolicy()
INTERNAL: Return the existence policy for this existence Query

        return this.existencePolicy;
    
public java.lang.ObjectgetObject()
PUBLIC: Return the object.

        return object;
    
public java.util.VectorgetPrimaryKey()
INTERNAL: Return the primaryKey.

        return primaryKey;
    
public java.lang.ClassgetReferenceClass()
Return the domain class associated with this query.

        return getObject().getClass();
    
public java.lang.StringgetReferenceClassName()
INTERNAL: Return the name of the reference class for this query Note: Although the API is designed to avoid requirement of classes being on the classpath, this is not a user defined query type, so it is ok to access the class.

        return getReferenceClass().getName();
    
protected voidprepare()
INTERNAL: Prepare the receiver for execution in a session.

        if (getDescriptor() == null) {
            //Bug#3947714  Pass the object instead of class in case object is proxy            
            setDescriptor(getSession().getDescriptor(getObject()));
        }

        if (getObject() != null) {// Prepare can be called without the object set yet.
            setObject(getDescriptor().getObjectBuilder().unwrapObject(getObject(), getSession()));
        }

        super.prepare();

        // It will only get to prepare if check database if required.
        getQueryMechanism().prepareDoesExist(getDoesExistField());
    
public voidprepareForExecution()
INTERNAL: Prepare the receiver for execution in a session.

        super.prepareForExecution();

        if (getObject() == null) {
            throw QueryException.objectToModifyNotSpecified(this);
        }
        setObject(getDescriptor().getObjectBuilder().unwrapObject(getObject(), getSession()));

        if (getDescriptor() == null) {
            setDescriptor(getSession().getDescriptor(getObject().getClass()));
        }

        if (getPrimaryKey() == null) {
            setPrimaryKey(getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(getObject(), getSession()));
        }

        if ((getTranslationRow() == null) || (getTranslationRow().isEmpty())) {
            setTranslationRow(getDescriptor().getObjectBuilder().buildRowForTranslation(getObject(), getSession()));
        }
    
public voidsetCheckCacheFirst(boolean checkCacheFirst)
INTERNAL: Sets checkCacheFirst flag. If true, existence check will first go to the cache. It will then check other options if it is not found in the cache

param
checkCacheFirst

        this.checkCacheFirst = checkCacheFirst;
    
public voidsetCheckDatabaseIfInvalid(boolean checkCacheFirst)
INTERNAL: Sets checkDatabaseIfInvalid flag. If true, query will go to the database when it finds the object in the cache and it is invalid. This is only valid when it checks the cache, and is true by default

param
checkDatabaseIfInvalid

        this.checkCacheFirst = checkCacheFirst;
    
public voidsetExistencePolicy(int existencePolicy)
INTERNAL: Set if the existence policy, this must be set to one of the constants.

        this.existencePolicy = existencePolicy;
    
public voidsetObject(java.lang.Object object)
PUBLIC: Set the object.

        this.object = object;
    
public voidsetPrimaryKey(java.util.Vector primaryKey)
INTERNAL: Set the primaryKey.

        this.primaryKey = primaryKey;
    
public booleanshouldAssumeExistenceForDoesExist()
PUBLIC: Returns true if the does exist check should be based only on whether the primary key of the object is set

        return existencePolicy == AssumeExistence;
    
public booleanshouldAssumeNonExistenceForDoesExist()
PUBLIC: Returns true if the does exist check should assume non existence.

        return existencePolicy == AssumeNonExistence;
    
public booleanshouldCheckCacheForDoesExist()
PUBLIC: Returns true if the does exist check should be based only on a cache check. Default behavior.

        return existencePolicy == CheckCache;
    
public booleanshouldCheckDatabaseForDoesExist()
PUBLIC: Returns true if the does exist check should query the database.

        return existencePolicy == CheckDatabase;