FileDocCategorySizeDatePackage
ReadAllQuery.javaAPI DocGlassfish v2 API23566Tue May 22 16:54:50 BST 2007oracle.toplink.essentials.queryframework

ReadAllQuery

public class ReadAllQuery extends ObjectLevelReadQuery
set

Purpose: Concrete class for all read queries involving a collection of objects.

Responsibilities: Return a container of the objects generated by the query. Implements the inheritance feature when dealing with abstract descriptors

author
Yvon Lavoie
since
TOPLink/Java 1.0

Fields Summary
protected Vector
orderByExpressions
Used for ordering support.
protected ContainerPolicy
containerPolicy
Used for collection and stream support.
Constructors Summary
public ReadAllQuery()
PUBLIC: Return a new read all query. A reference class must be specified before execution. It is better to provide the class and expression builder on construction to esnure a single expression builder is used. If no selection criteria is specified this will read all objects of the class from the database.

        super();
        this.useCollectionClass(ClassConstants.Vector_class);
    
public ReadAllQuery(Class classToRead)
PUBLIC: Return a new read all query. It is better to provide the class and expression builder on construction to esnure a single expression builder is used. If no selection criteria is specified this will read all objects of the class from the database.

        this();
        setReferenceClass(classToRead);
    
public ReadAllQuery(Class classToRead, Expression selectionCriteria)
PUBLIC: Return a new read all query for the class and the selection criteria.

        this();
        setReferenceClass(classToRead);
        setSelectionCriteria(selectionCriteria);
    
public ReadAllQuery(Class classToRead, ExpressionBuilder builder)
PUBLIC: Return a new read all query for the class. The expression builder must be used for all associated expressions used with the query.

        this();
        this.defaultBuilder = builder;
        setReferenceClass(classToRead);
    
public ReadAllQuery(Class classToRead, Call call)
PUBLIC: Return a new read all query. The call represents a database interaction such as SQL, Stored Procedure.

        this();
        setReferenceClass(classToRead);
        setCall(call);
    
public ReadAllQuery(ExpressionBuilder builder)
PUBLIC: The expression builder should be provide on creation to ensure only one is used.

        this();
        this.defaultBuilder = builder;
    
public ReadAllQuery(Call call)
PUBLIC: Create a read all query with the database call.

        this();
        setCall(call);
    
Methods Summary
public voidaddAscendingOrdering(java.lang.String queryKeyName)
PUBLIC: Order the query results by the object's attribute or query key name.

        addOrdering(getExpressionBuilder().get(queryKeyName).ascending());
    
public voidaddDescendingOrdering(java.lang.String queryKeyName)
PUBLIC: Order the query results by the object's attribute or query key name.

        addOrdering(getExpressionBuilder().get(queryKeyName).descending());
    
public voidaddOrdering(Expression orderingExpression)
PUBLIC: Add the ordering expression. This allows for ordering across relationships or functions. Example: readAllQuery.addOrdering(expBuilder.get("address").get("city").toUpperCase().descending())

        getOrderByExpressions().addElement(orderingExpression);
        //Bug2804042 Must un-prepare if prepared as the SQL may change.
        setIsPrepared(false);
    
protected java.lang.ObjectcheckEarlyReturnImpl(oracle.toplink.essentials.internal.sessions.AbstractSession session, oracle.toplink.essentials.internal.sessions.AbstractRecord translationRow)
INTERNAL: The cache check is done before the prepare as a hit will not require the work to be done.

        // Check for in-memory only query.
        if (shouldCheckCacheOnly()) {
            // assert !isReportQuery();
            if (shouldUseWrapperPolicy()) {
                getContainerPolicy().setElementDescriptor(getDescriptor());
            }

            // PERF: Fixed to not query each unit of work cache (is not conforming),
            // avoid hashtable and primary key indexing.
            // At some point we may need to support some kind of in-memory with conforming option,
            // but we do not currently allow this.
            AbstractSession rootSession = session;
            while (rootSession.isUnitOfWork()) {
                rootSession = ((UnitOfWorkImpl)rootSession).getParent();
            }
            Vector allCachedVector = rootSession.getIdentityMapAccessor().getAllFromIdentityMap(getSelectionCriteria(), getReferenceClass(), translationRow, getInMemoryQueryIndirectionPolicy(), false);

            // Must ensure that all of the objects returned are correctly registered in the unit of work.
            if (session.isUnitOfWork()) {
                allCachedVector = ((UnitOfWorkImpl)session).registerAllObjects(allCachedVector);
            }

            return getContainerPolicy().buildContainerFromVector(allCachedVector, session);
        } else {
            return null;
        }
    
protected DatabaseQuerycheckForCustomQuery(oracle.toplink.essentials.internal.sessions.AbstractSession session, oracle.toplink.essentials.internal.sessions.AbstractRecord translationRow)
INTERNAL: Check to see if a custom query should be used for this query. This is done before the query is copied and prepared/executed. null means there is none.

        checkDescriptor(session);

        // check if user defined a custom query
        if ((!isUserDefined()) && isExpressionQuery() && (getSelectionCriteria() == null) && (!hasOrderByExpressions()) && (getDescriptor().getQueryManager().hasReadAllQuery())) {
            return getDescriptor().getQueryManager().getReadAllQuery();
        } else {
            return null;
        }
    
public java.lang.Objectclone()
INTERNAL: Clone the query.

        ReadAllQuery cloneQuery = (ReadAllQuery)super.clone();

        // Don't use setters as that will trigger unprepare
        if (hasOrderByExpressions()) {
            cloneQuery.orderByExpressions = (Vector)getOrderByExpressions().clone();
        }
        cloneQuery.containerPolicy = getContainerPolicy().clone(cloneQuery);

        return cloneQuery;
    
protected java.lang.ObjectconformResult(java.lang.Object result, oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl unitOfWork, oracle.toplink.essentials.internal.sessions.AbstractRecord arguments, boolean buildDirectlyFromRows)
INTERNAL: Conform the result if specified.

        ContainerPolicy cp;
        IdentityHashtable indexedInterimResult = null;
        Expression selectionCriteriaClone = null;

        if (getSelectionCriteria() != null) {
            selectionCriteriaClone = (Expression)getSelectionCriteria().clone();
            selectionCriteriaClone.getBuilder().setSession(unitOfWork.getRootSession(null));
            selectionCriteriaClone.getBuilder().setQueryClass(getReferenceClass());
        }
        cp = getContainerPolicy();

        // This code is now a great deal different...  For one, registration is done
        // as part of conforming.  Also, this should only be called if one actually
        // is conforming.
        // First scan the UnitOfWork for conforming instances.
        // This will walk through the entire cache of registered objects.
        // Let p be objects from result not in the cache.
        // Let c be objects from cache.
        // Presently p intersect c = empty set, but later p subset c.
        // By checking cache now doesConform will be called p fewer times.
        indexedInterimResult = unitOfWork.scanForConformingInstances(selectionCriteriaClone, getReferenceClass(), arguments, this);

        // Now conform the result from the database.
        // Remove any deleted or changed objects that no longer conform.
        // Deletes will only work for simple queries, queries with or's or anyof's may not return
        // correct results when untriggered indirection is in the model.		
        Vector fromDatabase = null;

        // When building directly from rows, one of the performance benefits
        // is that we no longer have to wrap and then unwrap the originals.
        // result is just a vector, not a container of wrapped originals.
        if (buildDirectlyFromRows) {
            Vector rows = (Vector)result;
            Set identitySet = null;
            fromDatabase = new Vector(rows.size());
            for (int i = 0; i < rows.size(); i++) {
                Object object = rows.elementAt(i);

                // null is placed in the row collection for 1-m joining to filter duplicate rows.
                if (object != null) {
                    Object clone = conformIndividualResult(object, unitOfWork, arguments, selectionCriteriaClone, indexedInterimResult, buildDirectlyFromRows);
                    if (clone != null) {
                        // Avoid duplicates if -m joining was used and a cache hit occured.
                        if (getJoinedAttributeManager().isToManyJoin()) {
                            if (identitySet == null) {
                                identitySet = new TopLinkIdentityHashSet(rows.size());
                            }
                            if (!identitySet.contains(clone)) {
                                identitySet.add(clone);
                                fromDatabase.addElement(clone);
                            }
                        } else {
                            fromDatabase.addElement(clone);
                        }
                    }
                }
            }
        } else {
            fromDatabase = new Vector(cp.sizeFor(result));
            AbstractSession sessionToUse = unitOfWork.getParent();
            for (Object iter = cp.iteratorFor(result); cp.hasNext(iter);) {
                Object object = cp.next(iter, sessionToUse);
                Object clone = conformIndividualResult(object, unitOfWork, arguments, selectionCriteriaClone, indexedInterimResult, buildDirectlyFromRows);
                if (clone != null) {
                    fromDatabase.addElement(clone);
                }
            }
        }

        // Now add the unwrapped conforming instances into an appropriate container.  
        // Wrapping is done automatically.
        // Make sure a vector of exactly the right size is returned.
        //
        Object conformedResult = cp.containerInstance(indexedInterimResult.size() + fromDatabase.size());
        Object eachClone;
        for (Enumeration enumtr = indexedInterimResult.elements(); enumtr.hasMoreElements();) {
            eachClone = enumtr.nextElement();
            cp.addInto(eachClone, conformedResult, unitOfWork);
        }
        for (Enumeration enumtr = fromDatabase.elements(); enumtr.hasMoreElements();) {
            eachClone = enumtr.nextElement();
            cp.addInto(eachClone, conformedResult, unitOfWork);
        }
        return conformedResult;
    
protected java.lang.ObjectexecuteObjectLevelReadQuery()
INTERNAL: Execute the query. Get the rows and build the object from the rows.

exception
DatabaseException - an error has occurred on the database
return
java.lang.Object collection of objects resulting from execution of query.

        Object result = null;
        if (getContainerPolicy().overridesRead()) {
            return getContainerPolicy().execute();
        }

        Vector rows = getQueryMechanism().selectAllRows();
        setExecutionTime(System.currentTimeMillis());
        // If using -m joins, must set all rows.
        if (getJoinedAttributeManager().isToManyJoin()) {
            getJoinedAttributeManager().setDataResults(rows, getSession());
        }

        if (getSession().isUnitOfWork()) {
            result = registerResultInUnitOfWork(rows, (UnitOfWorkImpl)getSession(), getTranslationRow(), true);// 
        } else {
            result = getQueryMechanism().buildObjectsFromRows(rows);
        }

        if (shouldIncludeData()) {
            ComplexQueryResult complexResult = new ComplexQueryResult();
            complexResult.setResult(result);
            complexResult.setData(rows);
            return complexResult;
        }

        return result;
    
public ContainerPolicygetContainerPolicy()
INTERNAL: Return the query's container policy.

return
oracle.toplink.essentials.internal.queryframework.ContainerPolicy

        return containerPolicy;
    
public java.util.VectorgetOrderByExpressions()
INTERNAL: Return the order expressions for the query.

        if (orderByExpressions == null) {
            orderByExpressions = new Vector();
        }
        return orderByExpressions;
    
public booleanhasBatchReadAttributes()
INTERNAL: Return true is this query has batching

        return false;
    
public booleanhasHierarchicalExpressions()
INTERNAL: Verify that we have hierarchical query expressions

        return false;
    
public booleanhasOrderByExpressions()
INTERNAL: The order bys are lazy initialized to conserv space.

        return orderByExpressions != null;
    
public booleanisAttributeBatchRead(java.lang.String attributeName)
INTERNAL: Return if the attribute is specified for batch reading.

        return false;
    
public booleanisReadAllQuery()
PUBLIC: Return if this is a read all query.

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

        super.prepare();

        getContainerPolicy().prepare(this, getSession());

        if (getContainerPolicy().overridesRead()) {
            return;
        }

        prepareSelectAllRows();
    
protected voidprepareCustomQuery(DatabaseQuery customQuery)
INTERNAL: Set the properties needed to be cascaded into the custom query.

        ReadAllQuery customReadQuery = (ReadAllQuery)customQuery;
        customReadQuery.setContainerPolicy(getContainerPolicy());
        customReadQuery.setCascadePolicy(getCascadePolicy());
        customReadQuery.setShouldRefreshIdentityMapResult(shouldRefreshIdentityMapResult());
        customReadQuery.setShouldMaintainCache(shouldMaintainCache());
        customReadQuery.setShouldUseWrapperPolicy(shouldUseWrapperPolicy());
    
public voidprepareForExecution()
INTERNAL: Prepare the receiver for execution in a session.

        super.prepareForExecution();

        getContainerPolicy().prepareForExecution();

    
protected voidprepareSelectAllRows()
INTERNAL: Prepare the mechanism.

        getQueryMechanism().prepareSelectAllRows();
    
public java.lang.ObjectregisterResultInUnitOfWork(java.lang.Object result, oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl unitOfWork, oracle.toplink.essentials.internal.sessions.AbstractRecord arguments, boolean buildDirectlyFromRows)
INTERNAL: All objects queried via a UnitOfWork get registered here. If the query went to the database.

Involves registering the query result individually and in totality, and hence refreshing / conforming is done here.

param
result may be collection (read all) or an object (read one), or even a cursor. If in transaction the shared cache will be bypassed, meaning the result may not be originals from the parent but raw database rows.
param
unitOfWork the unitOfWork the result is being registered in.
param
arguments the original arguments/parameters passed to the query execution. Used by conforming
param
buildDirectlyFromRows If in transaction must construct a registered result from raw database rows.
return
the final (conformed, refreshed, wrapped) UnitOfWork query result

        // For bug 2612366: Conforming results in UOW extremely slow.
        // Replacing results with registered versions in the UOW is a part of 
        // conforming and is now done while conforming to maximize performance.
        if (shouldConformResultsInUnitOfWork() || getDescriptor().shouldAlwaysConformResultsInUnitOfWork()) {
            return conformResult(result, unitOfWork, arguments, buildDirectlyFromRows);
        }

        // When building directly from rows, one of the performance benefits
        // is that we no longer have to wrap and then unwrap the originals.
        // result is just a vector, not a collection of wrapped originals.
        // Also for cursors the initial connection is automatically registered.
        if (buildDirectlyFromRows) {
            Vector rows = (Vector)result;
            Set identitySet = null;
            ContainerPolicy cp = getContainerPolicy();
            Object clones = cp.containerInstance(rows.size());
            for (Enumeration enumtr = rows.elements(); enumtr.hasMoreElements();) {
                Object row = enumtr.nextElement();

                // null is placed in the row collection for 1-m joining to filter duplicate rows.
                if (row != null) {
                    Object clone = registerIndividualResult(row, unitOfWork, buildDirectlyFromRows, null);

                    // Avoid duplicates if -m joining was used and a cache hit occured.
                    if (getJoinedAttributeManager().isToManyJoin()) {
                        if (identitySet == null) {
                            identitySet = new TopLinkIdentityHashSet(rows.size());
                        }
                        if (!identitySet.contains(clone)) {
                            identitySet.add(clone);
                            cp.addInto(clone, clones, unitOfWork);
                        }
                    } else {
                        cp.addInto(clone, clones, unitOfWork);
                    }
                }
            }
            return clones;
        }

        ContainerPolicy cp;
        cp = getContainerPolicy();

        Object clones = cp.containerInstance(cp.sizeFor(result));
        AbstractSession sessionToUse = unitOfWork.getParent();
        for (Object iter = cp.iteratorFor(result); cp.hasNext(iter);) {
            Object object = cp.next(iter, sessionToUse);
            Object clone = registerIndividualResult(object, unitOfWork, buildDirectlyFromRows, null);
            cp.addInto(clone, clones, unitOfWork);
        }
        return clones;
    
public voidsetContainerPolicy(ContainerPolicy containerPolicy)
PUBLIC: Set the container policy. Used to support different containers (e.g. Collections, Maps).

        // CR#... a container policy is always required, default is vector,
        // required for deployment XML.
        if (containerPolicy == null) {
            return;
        }
        this.containerPolicy = containerPolicy;
        setIsPrepared(false);
    
public voidsetOrderByExpressions(java.util.Vector orderByExpressions)
INTERNAL: Set the order expressions for the query.

        this.orderByExpressions = orderByExpressions;
    
public voiduseCollectionClass(java.lang.Class concreteClass)
PUBLIC: Configure the mapping to use an instance of the specified container class to hold the target objects.

jdk1.2.x: The container class must implement (directly or indirectly) the Collection interface.

jdk1.1.x: The container class must be a subclass of Vector.

        // Set container policy.
        setContainerPolicy(ContainerPolicy.buildPolicyFor(concreteClass));

    
public voiduseMapClass(java.lang.Class concreteClass, java.lang.String methodName)
PUBLIC: Configure the query to use an instance of the specified container class to hold the result objects. The key used to index the value in the Map is the value returned by a call to the specified zero-argument method. The method must be implemented by the class (or a superclass) of the value to be inserted into the Map.

jdk1.2.x: The container class must implement (directly or indirectly) the Map interface.

jdk1.1.x: The container class must be a subclass of Hashtable.

The referenceClass must set before calling this method.

        // the reference class has to be specified before coming here
        if (getReferenceClass() == null) {
            throw QueryException.referenceClassMissing(this);
        }
        ContainerPolicy policy = ContainerPolicy.buildPolicyFor(concreteClass);
        policy.setKeyName(methodName, getReferenceClass().getName());
        setContainerPolicy(policy);