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

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

There is a newer version: 4.2.1
Show newest version
/*****************************************************************
 *   Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 ****************************************************************/

package org.apache.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.apache.cayenne.access.jdbc.ColumnDescriptor;
import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.map.MapLoader;
import org.apache.cayenne.map.Procedure;
import org.apache.cayenne.util.XMLEncoder;
import org.apache.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.apache.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.apache.cayenne.access.DataContext#performGenericQuery(Query)}. *

*/ public class ProcedureQuery extends AbstractQuery implements ParameterizedQuery, XMLSerializable { static final String COLUMN_NAME_CAPITALIZATION_PROPERTY = "cayenne.ProcedureQuery.columnNameCapitalization"; /** * @since 1.2 */ protected String resultEntityName; /** * @since 1.2 */ protected Class resultClass; protected CapsStrategy columnNamesCapitalization; protected Map parameters = new HashMap(); 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. The query would fetch DataRows. Fetching * Persistent objects can be achieved either by using * {@link #ProcedureQuery(String, Class)} constructor or by calling * {@link #setFetchingDataRows(boolean)} and {@link #setResultEntityName(String)} * methods. */ public ProcedureQuery() { // for backwards compatibility we go against usual default... metaData.setFetchingDataRows(true); } /** * Creates a ProcedureQuery based on a Procedure object. The query would fetch * DataRows. Fetching Persistent objects can be achieved either by using * {@link #ProcedureQuery(String, Class)} constructor or by calling * {@link #setFetchingDataRows(boolean)} and {@link #setResultEntityName(String)} * methods. */ 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. The query would fetch * DataRows. Fetching Persistent objects can be achieved either by using * {@link #ProcedureQuery(String, Class)} constructor or by calling * {@link #setFetchingDataRows(boolean)} and {@link #setResultEntityName(String)} * methods. * * @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; } /** * @since 1.1 */ public ProcedureQuery(String procedureName, Class resultType) { setRoot(procedureName); this.resultClass = resultType; } /** * @since 1.2 */ @Override public QueryMetadata getMetaData(EntityResolver resolver) { metaData.resolve( root, resultClass != null ? resultClass : resultEntityName, resolver, this); return metaData; } /** * Returns a List of descriptors for 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 */ @Override 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; } Object columnNamesCapitalization = properties .get(COLUMN_NAME_CAPITALIZATION_PROPERTY); this.columnNamesCapitalization = (columnNamesCapitalization != null) ? CapsStrategy .valueOf(columnNamesCapitalization.toString().toUpperCase()) : null; 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); if (getColumnNamesCapitalization() != CapsStrategy.DEFAULT) { encoder.printProperty( COLUMN_NAME_CAPITALIZATION_PROPERTY, getColumnNamesCapitalization().name()); } 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.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; } /** * @since 3.0 */ public QueryCacheStrategy getCacheStrategy() { return metaData.getCacheStrategy(); } /** * @since 3.0 */ public void setCacheStrategy(QueryCacheStrategy strategy) { metaData.setCacheStrategy(strategy); } /** * @since 3.0 */ public String[] getCacheGroups() { return metaData.getCacheGroups(); } /** * @since 3.0 */ public void setCacheGroups(String... cacheGroups) { this.metaData.setCacheGroups(cacheGroups); } public int getFetchLimit() { return metaData.getFetchLimit(); } public void setFetchLimit(int fetchLimit) { this.metaData.setFetchLimit(fetchLimit); } /** * @since 3.0 */ public int getFetchOffset() { return metaData.getFetchOffset(); } /** * @since 3.0 */ public void setFetchOffset(int fetchOffset) { metaData.setFetchOffset(fetchOffset); } 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(); } /** * 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(); } /** * @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; } /** * @since 3.0 */ public CapsStrategy getColumnNamesCapitalization() { return columnNamesCapitalization != null ? columnNamesCapitalization : CapsStrategy.DEFAULT; } /** * @since 3.0 */ public void setColumnNamesCapitalization(CapsStrategy columnNameCapitalization) { this.columnNamesCapitalization = columnNameCapitalization; } /** * Sets statement's fetch size (0 for no default size) * * @since 3.0 */ public void setStatementFetchSize(int size) { metaData.setStatementFetchSize(size); } /** * @return statement's fetch size * @since 3.0 */ public int getStatementFetchSize() { return metaData.getStatementFetchSize(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy