All Downloads are FREE. Search and download functionalities are using the official Maven repository.

oracle.toplink.essentials.queryframework.ReadAllQuery Maven / Gradle / Ivy

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * // Copyright (c) 1998, 2007, Oracle. All rights reserved.
 * 
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package oracle.toplink.essentials.queryframework;

import java.util.*;
import oracle.toplink.essentials.internal.helper.*;
import oracle.toplink.essentials.internal.queryframework.*;
import oracle.toplink.essentials.exceptions.*;
import oracle.toplink.essentials.expressions.*;
import oracle.toplink.essentials.internal.sessions.AbstractRecord;
import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl;
import oracle.toplink.essentials.internal.sessions.AbstractSession;

/**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 */ public class ReadAllQuery extends ObjectLevelReadQuery { /** Used for ordering support. */ protected Vector orderByExpressions; /** Used for collection and stream support. */ protected ContainerPolicy containerPolicy; /** * 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. */ public ReadAllQuery() { super(); this.useCollectionClass(ClassConstants.Vector_class); } /** * 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. */ public ReadAllQuery(Class classToRead) { this(); setReferenceClass(classToRead); } /** * PUBLIC: * Return a new read all query for the class and the selection criteria. */ public ReadAllQuery(Class classToRead, Expression selectionCriteria) { this(); setReferenceClass(classToRead); setSelectionCriteria(selectionCriteria); } /** * PUBLIC: * Return a new read all query for the class. * The expression builder must be used for all associated expressions used with the query. */ public ReadAllQuery(Class classToRead, ExpressionBuilder builder) { this(); this.defaultBuilder = builder; setReferenceClass(classToRead); } /** * PUBLIC: * Return a new read all query. * The call represents a database interaction such as SQL, Stored Procedure. */ public ReadAllQuery(Class classToRead, Call call) { this(); setReferenceClass(classToRead); setCall(call); } /** * PUBLIC: * The expression builder should be provide on creation to ensure only one is used. */ public ReadAllQuery(ExpressionBuilder builder) { this(); this.defaultBuilder = builder; } /** * PUBLIC: * Create a read all query with the database call. */ public ReadAllQuery(Call call) { this(); setCall(call); } /** * PUBLIC: * Order the query results by the object's attribute or query key name. */ public void addAscendingOrdering(String queryKeyName) { addOrdering(getExpressionBuilder().get(queryKeyName).ascending()); } /** * PUBLIC: * Order the query results by the object's attribute or query key name. */ public void addDescendingOrdering(String queryKeyName) { addOrdering(getExpressionBuilder().get(queryKeyName).descending()); } /** * PUBLIC: * Add the ordering expression. This allows for ordering across relationships or functions. * Example: readAllQuery.addOrdering(expBuilder.get("address").get("city").toUpperCase().descending()) */ public void addOrdering(Expression orderingExpression) { getOrderByExpressions().addElement(orderingExpression); //Bug2804042 Must un-prepare if prepared as the SQL may change. setIsPrepared(false); } /** * INTERNAL: * The cache check is done before the prepare as a hit will not require the work to be done. */ protected Object checkEarlyReturnImpl(AbstractSession session, AbstractRecord translationRow) { // 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; } } /** * 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. */ protected DatabaseQuery checkForCustomQuery(AbstractSession session, AbstractRecord translationRow) { 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; } } /** * INTERNAL: * Clone the query. */ public Object clone() { 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; } /** * INTERNAL: * Conform the result if specified. */ protected Object conformResult(Object result, UnitOfWorkImpl unitOfWork, AbstractRecord arguments, boolean buildDirectlyFromRows) { 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; } /** * 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. */ protected Object executeObjectLevelReadQuery() throws DatabaseException { 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; } /** * INTERNAL: * Return the query's container policy. * @return oracle.toplink.essentials.internal.queryframework.ContainerPolicy */ public ContainerPolicy getContainerPolicy() { return containerPolicy; } /** * INTERNAL: * Return the order expressions for the query. */ public Vector getOrderByExpressions() { if (orderByExpressions == null) { orderByExpressions = new Vector(); } return orderByExpressions; } /** * INTERNAL: * The order bys are lazy initialized to conserv space. */ public boolean hasOrderByExpressions() { return orderByExpressions != null; } /** * INTERNAL: * Verify that we have hierarchical query expressions */ public boolean hasHierarchicalExpressions() { return false; } /** * INTERNAL: * Return true is this query has batching */ public boolean hasBatchReadAttributes() { return false; } /** * INTERNAL: * Return if the attribute is specified for batch reading. */ public boolean isAttributeBatchRead(String attributeName) { return false; } /** * PUBLIC: * Return if this is a read all query. */ public boolean isReadAllQuery() { return true; } /** * INTERNAL: * Prepare the receiver for execution in a session. */ protected void prepare() throws QueryException { super.prepare(); getContainerPolicy().prepare(this, getSession()); if (getContainerPolicy().overridesRead()) { return; } prepareSelectAllRows(); } /** * INTERNAL: * Set the properties needed to be cascaded into the custom query. */ protected void prepareCustomQuery(DatabaseQuery customQuery) { ReadAllQuery customReadQuery = (ReadAllQuery)customQuery; customReadQuery.setContainerPolicy(getContainerPolicy()); customReadQuery.setCascadePolicy(getCascadePolicy()); customReadQuery.setShouldRefreshIdentityMapResult(shouldRefreshIdentityMapResult()); customReadQuery.setShouldMaintainCache(shouldMaintainCache()); customReadQuery.setShouldUseWrapperPolicy(shouldUseWrapperPolicy()); } /** * INTERNAL: * Prepare the receiver for execution in a session. */ public void prepareForExecution() throws QueryException { super.prepareForExecution(); getContainerPolicy().prepareForExecution(); } /** * INTERNAL: * Prepare the mechanism. */ protected void prepareSelectAllRows() { getQueryMechanism().prepareSelectAllRows(); } /** * 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 */ public Object registerResultInUnitOfWork(Object result, UnitOfWorkImpl unitOfWork, AbstractRecord arguments, boolean buildDirectlyFromRows) { // 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: * Set the container policy. Used to support different containers * (e.g. Collections, Maps). */ public void setContainerPolicy(ContainerPolicy containerPolicy) { // CR#... a container policy is always required, default is vector, // required for deployment XML. if (containerPolicy == null) { return; } this.containerPolicy = containerPolicy; setIsPrepared(false); } /** * INTERNAL: * Set the order expressions for the query. */ public void setOrderByExpressions(Vector orderByExpressions) { this.orderByExpressions = orderByExpressions; } /** * 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. */ public void useCollectionClass(Class concreteClass) { // Set container policy. setContainerPolicy(ContainerPolicy.buildPolicyFor(concreteClass)); } /** * 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. */ public void useMapClass(Class concreteClass, String methodName) { // 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); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy