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

org.objectstyle.cayenne.query.ProcedureQuery Maven / Gradle / Ivy

Go to download

Cayenne Object Persistence Framework including all dependencies.

The newest version!
/* ====================================================================
 *
 * The ObjectStyle Group Software License, version 1.1
 * ObjectStyle Group - http://objectstyle.org/
 * 
 * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
 * of the software. All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 
 * 3. The end-user documentation included with the redistribution, if any,
 *    must include the following acknowlegement:
 *    "This product includes software developed by independent contributors
 *    and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 * 
 * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
 *    or promote products derived from this software without prior written
 *    permission. For written permission, email
 *    "andrus at objectstyle dot org".
 * 
 * 5. Products derived from this software may not be called "ObjectStyle"
 *    or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
 *    names without prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 * 
 * This software consists of voluntary contributions made by many
 * individuals and hosted on ObjectStyle Group web site.  For more
 * information on the ObjectStyle Group, please see
 * .
 */

package org.objectstyle.cayenne.query;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.objectstyle.cayenne.access.jdbc.ColumnDescriptor;
import org.objectstyle.cayenne.access.jdbc.RowDescriptor;
import org.objectstyle.cayenne.map.EntityResolver;
import org.objectstyle.cayenne.map.Procedure;
import org.objectstyle.cayenne.map.QueryBuilder;
import org.objectstyle.cayenne.util.XMLEncoder;
import org.objectstyle.cayenne.util.XMLSerializable;

/**
 * A query based on Procedure. Can be used as a select query, or as a query of an
 * arbitrary complexity, performing data modification, selecting data (possibly with
 * multiple result sets per call), returning values via OUT parameters.
 * 

Execution with DataContext

*

Reading OUT parameters

*

* If a ProcedureQuery has OUT parameters, they are wrapped in a separate List in the * query result. Such list will contain a single Map with OUT parameter values. *

*

Using ProcedureQuery as a GenericSelectQuery

*

* Executing ProcedureQuery via * {@link org.objectstyle.cayenne.access.DataContext#performQuery(Query)} makes sense only * if the stored procedure returns a single result set (or alternatively returns a result * via OUT parameters and no other result sets). It is still OK if data modification * occurs as a side effect. However if the query returns more then one result set, a more * generic form should be used: * {@link org.objectstyle.cayenne.access.DataContext#performGenericQuery(Query)}. *

* * @author Andrus Adamchik */ public class ProcedureQuery extends AbstractQuery implements GenericSelectQuery, ParameterizedQuery, XMLSerializable { /** * If set, allows to fetch results as DataObjects. * * @since 1.1 * @deprecated since 1.2 'resultEntityName' must be used. */ protected String resultClassName; /** * @since 1.2 */ protected String resultEntityName; /** * @since 1.2 */ protected Class resultClass; protected Map parameters = new HashMap(); /** * @deprecated since 1.2 as this information is no longer relavant to Cayenne */ protected boolean selecting; ProcedureQueryMetadata metaData = new ProcedureQueryMetadata(); // TODO: ColumnDescriptor is not XMLSerializable so we can't store // it in a DataMap /** * @since 1.2 */ protected List resultDescriptors; /** * Creates an empty procedure query. */ public ProcedureQuery() { // for backwards compatibility we go against usual default... metaData.setFetchingDataRows(true); } /** * Creates a ProcedureQuery based on a Procedure object. */ public ProcedureQuery(Procedure procedure) { // for backwards compatibility we go against usual default... metaData.setFetchingDataRows(true); setRoot(procedure); } /** * Creates a ProcedureQuery based on a stored procedure. *

* Performance Note: with current EntityResolver implementation it is preferrable to * use Procedure object instead of String as a query root. String root can cause * unneeded EntityResolver reindexing on every call. See this mailing list thread: * http://objectstyle.org/cayenne/lists/cayenne-user/2005/01/0109.html *

* * @param procedureName A name of the stored procedure. For this query to work, a * procedure with this name must be mapped in Cayenne. */ public ProcedureQuery(String procedureName) { // for backwards compatibility we go against usual default... metaData.setFetchingDataRows(true); setRoot(procedureName); } /** * @since 1.1 */ public ProcedureQuery(Procedure procedure, Class resultType) { setRoot(procedure); this.resultClass = resultType; // call this for backwards compatibility setResultClassName(resultType != null ? resultType.getName() : null); } /** *

* Performance Note: with current EntityResolver implementation it is preferrable to * use Procedure object instead of String as a query root. String root can cause * unneeded EntityResolver reindexing on every call. See this mailing list thread: * http://objectstyle.org/cayenne/lists/cayenne-user/2005/01/0109.html *

* * @since 1.1 */ public ProcedureQuery(String procedureName, Class resultType) { setRoot(procedureName); this.resultClass = resultType; setResultClassName(resultType != null ? resultType.getName() : null); } /** * @since 1.2 */ public QueryMetadata getMetaData(EntityResolver resolver) { metaData.resolve(root, resultClass != null ? (Object) resultClass : resultEntityName, resolver, getName()); return metaData; } /** * Returns a List of #{@link RowDescriptor} objects describing query ResultSets in * the order they are returned by the stored procedure. *

* Note that if a procedure returns ResultSet in an OUT parameter, it is returned * prior to any other result sets (though in practice database engines usually support * only one mechanism for returning result sets. *

* * @since 1.2 */ public List getResultDescriptors() { return resultDescriptors != null ? resultDescriptors : Collections.EMPTY_LIST; } /** * Adds a descriptor for a single ResultSet. More than one descriptor can be added by * calling this method multiple times in the order of described ResultSet appearance * in the procedure results. * * @since 1.2 */ public synchronized void addResultDescriptor(ColumnDescriptor[] descriptor) { if (resultDescriptors == null) { resultDescriptors = new ArrayList(2); } resultDescriptors.add(descriptor); } /** * Removes result descriptor from the list of descriptors. * * @since 1.2 */ public void removeResultDescriptor(ColumnDescriptor[] descriptor) { if (resultDescriptors != null) { resultDescriptors.remove(descriptor); } } /** * Calls "makeProcedure" on the visitor. * * @since 1.2 */ public SQLAction createSQLAction(SQLActionVisitor visitor) { return visitor.procedureAction(this); } /** * Initializes query parameters using a set of properties. * * @since 1.1 */ public void initWithProperties(Map properties) { // must init defaults even if properties are empty if (properties == null) { properties = Collections.EMPTY_MAP; } metaData.initWithProperties(properties); } /** * Prints itself as XML to the provided PrintWriter. * * @since 1.1 */ public void encodeAsXML(XMLEncoder encoder) { encoder.print(""); encoder.indent(1); metaData.encodeAsXML(encoder); encoder.indent(-1); encoder.println(""); } /** * Creates and returns a new ProcedureQuery built using this query as a prototype and * substituting template parameters with the values from the map. * * @since 1.1 */ public Query createQuery(Map parameters) { // create a query replica ProcedureQuery query = new ProcedureQuery(); if (root != null) { query.setRoot(root); } query.setResultClassName(resultClassName); query.setResultEntityName(resultEntityName); query.metaData.copyFromInfo(this.metaData); query.setParameters(parameters); // TODO: implement algorithm for building the name based on the original name and // the hashcode of the map of parameters. This way query clone can take advantage // of caching. return query; } public String getCachePolicy() { return metaData.getCachePolicy(); } public void setCachePolicy(String policy) { this.metaData.setCachePolicy(policy); } public int getFetchLimit() { return metaData.getFetchLimit(); } public void setFetchLimit(int fetchLimit) { this.metaData.setFetchLimit(fetchLimit); } public int getPageSize() { return metaData.getPageSize(); } public void setPageSize(int pageSize) { metaData.setPageSize(pageSize); } public void setFetchingDataRows(boolean flag) { metaData.setFetchingDataRows(flag); } public boolean isFetchingDataRows() { return metaData.isFetchingDataRows(); } public boolean isRefreshingObjects() { return metaData.isRefreshingObjects(); } public void setRefreshingObjects(boolean flag) { metaData.setRefreshingObjects(flag); } public boolean isResolvingInherited() { return metaData.isResolvingInherited(); } public void setResolvingInherited(boolean b) { metaData.setResolvingInherited(b); } /** * Adds a named parameter to the internal map of parameters. * * @since 1.1 */ public synchronized void addParameter(String name, Object value) { parameters.put(name, value); } /** * @since 1.1 */ public synchronized void removeParameter(String name) { parameters.remove(name); } /** * Returns a map of procedure parameters. * * @since 1.1 */ public Map getParameters() { return parameters; } /** * Sets a map of parameters. * * @since 1.1 */ public synchronized void setParameters(Map parameters) { this.parameters.clear(); if (parameters != null) { this.parameters.putAll(parameters); } } /** * Cleans up all configured parameters. * * @since 1.1 */ public synchronized void clearParameters() { this.parameters.clear(); } /** * Returns an optional result type of the query. * * @since 1.1 * @deprecated since 1.2 use {@link #getResultEntityName()} */ public String getResultClassName() { return resultClassName; } /** * Returns Java class of the DataObjects returned by this query. * * @deprecated since 1.2 * @since 1.1 */ public Class getResultClass(ClassLoader classLoader) { return resultClass; } /** * Sets optional result type of the query. A Class of the result type must be a * DataObject implementation mapped in Cayenne. * * @since 1.1 * @deprecated since 1.2 use {@link #setResultEntityName(String)} */ public void setResultClassName(String resultClassName) { this.resultClassName = resultClassName; } /** * Returns true if ProcedureQuery is expected to return a ResultSet. * * @since 1.1 * @deprecated since 1.2 as this information is no longer relavant to Cayenne */ public boolean isSelecting() { return selecting; } /** * Sets whether ProcedureQuery is expected to return a ResultSet. * * @since 1.1 * @deprecated since 1.2 as this information is no longer relavant to Cayenne */ public void setSelecting(boolean b) { selecting = b; } /** * @since 1.2 */ public PrefetchTreeNode getPrefetchTree() { return metaData.getPrefetchTree(); } /** * Adds a prefetch. * * @since 1.2 */ public PrefetchTreeNode addPrefetch(String prefetchPath) { // by default use JOINT_PREFETCH_SEMANTICS return metaData.addPrefetch( prefetchPath, PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS); } /** * @since 1.2 */ public void removePrefetch(String prefetch) { metaData.removePrefetch(prefetch); } /** * Adds all prefetches from a provided collection. * * @since 1.2 */ public void addPrefetches(Collection prefetches) { metaData.addPrefetches(prefetches, PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS); } /** * Clears all prefetches. * * @since 1.2 */ public void clearPrefetches() { metaData.clearPrefetches(); } /** * @since 1.2 */ public String getResultEntityName() { return resultEntityName; } /** * @since 1.2 */ public void setResultEntityName(String resultEntityName) { this.resultEntityName = resultEntityName; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy