
org.springframework.jdbc.object.SqlQuery Maven / Gradle / Ivy
/*
* Copyright 2002-2006 the original author or authors.
*
* Licensed 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.springframework.jdbc.object;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterUtils;
/**
* Reusable object to represent a SQL query. Like all RdbsOperation
* objects, SqlQuery objects are threadsafe after their initialization is
* complete. That is, after they are constructed and configured via their
* setter methods, they can be used safely from multiple threads.
*
* Subclasses must implement the newRowMapper
method to provide an object
* that can extract the results of iterating over the ResultSet.
*
*
This class provides a number of public execute
methods that are
* analogous to the different convenient JDO query execute methods. Subclasses
* can either rely on one of these inherited methods, or can add their own
* custom execution methods, with meaningful names and typed parameters. Each
* custom query method will invoke one of this class's untyped query methods.
*
* @author Rod Johnson
* @author Thomas Risberg
* @author Jean-Pierre Pawlak
*/
public abstract class SqlQuery extends SqlOperation {
/** Number of rows to expect. If 0, unknown. */
private int rowsExpected = 0;
/**
* Constructor to allow use as a JavaBean. DataSource and SQL
* must be supplied before compilation and use.
*/
public SqlQuery() {
}
/**
* Convenient constructor with DataSource and SQL string.
* @param ds DataSource to use to get connections
* @param sql to execute. SQL can also be supplied at runtime
* by overriding the getSql() method.
*/
public SqlQuery(DataSource ds, String sql) {
setDataSource(ds);
setSql(sql);
}
/**
* Set the number of rows expected. This can be used to ensure
* efficient storage of results. The default behavior is not to
* expect any specific number of rows.
*/
public void setRowsExpected(int rowsExpected) {
this.rowsExpected = rowsExpected;
}
/**
* Get the number of rows expected.
*/
public int getRowsExpected() {
return rowsExpected;
}
/**
* Central execution method. All un-named parameter execution goes through this method.
* @param params parameters, similar to JDO query parameters.
* Primitive parameters must be represented by their Object wrapper type.
* The ordering of parameters is significant.
* @param context contextual information passed to the callback mapRow
method.
* The JDBC operation itself doesn't rely on this parameter, but can be useful for
* creating the objects of the result list.
* @return a List of objects, one per row of the ResultSet. Normally all these
* will be of the same class, although it is possible to use different types.
*/
public List execute(Object[] params, Map context) throws DataAccessException {
validateParameters(params);
RowMapper rowMapper = newRowMapper(params, context);
return getJdbcTemplate().query(newPreparedStatementCreator(params), rowMapper);
}
/**
* Convenient method to execute without context.
* @param params parameters for the query. Primitive parameters must
* be represented by their Object wrapper type. The ordering of parameters is
* significant.
*/
public List execute(Object[] params) throws DataAccessException {
return execute(params, null);
}
/**
* Convenient method to execute without parameters.
* @param context the contextual information for object creation
*/
public List execute(Map context) throws DataAccessException {
return execute((Object[]) null, context);
}
/**
* Convenient method to execute without parameters nor context.
*/
public List execute() throws DataAccessException {
return execute((Object[]) null);
}
/**
* Convenient method to execute with a single int parameter and context.
* @param p1 single int parameter
* @param context the contextual information for object creation
*/
public List execute(int p1, Map context) throws DataAccessException {
return execute(new Object[] {new Integer(p1)}, context);
}
/**
* Convenient method to execute with a single int parameter.
* @param p1 single int parameter
*/
public List execute(int p1) throws DataAccessException {
return execute(p1, null);
}
/**
* Convenient method to execute with two int parameters and context.
* @param p1 first int parameter
* @param p2 second int parameter
* @param context the contextual information for object creation
*/
public List execute(int p1, int p2, Map context) throws DataAccessException {
return execute(new Object[] {new Integer(p1), new Integer(p2)}, context);
}
/**
* Convenient method to execute with two int parameters.
* @param p1 first int parameter
* @param p2 second int parameter
*/
public List execute(int p1, int p2) throws DataAccessException {
return execute(p1, p2, null);
}
/**
* Convenient method to execute with a single long parameter and context.
* @param p1 single long parameter
* @param context the contextual information for object creation
*/
public List execute(long p1, Map context) throws DataAccessException {
return execute(new Object[] {new Long(p1)}, context);
}
/**
* Convenient method to execute with a single long parameter.
* @param p1 single long parameter
*/
public List execute(long p1) throws DataAccessException {
return execute(p1, null);
}
/**
* Convenient method to execute with a single String parameter and context.
* @param p1 single String parameter
* @param context the contextual information for object creation
*/
public List execute(String p1, Map context) throws DataAccessException {
return execute(new Object[] {p1}, context);
}
/**
* Convenient method to execute with a single String parameter.
* @param p1 single String parameter
*/
public List execute(String p1) throws DataAccessException {
return execute(p1, null);
}
/**
* Central execution method. All named parameter execution goes through this method.
* @param paramMap parameters associated with the name specified while declaring
* the SqlParameters. Primitive parameters must be represented by their Object wrapper
* type. The ordering of parameters is not significant since they are supplied in a
* SqlParameterMap which is an implementation of the Map interface.
* @param context contextual information passed to the callback mapRow
method.
* The JDBC operation itself doesn't reyl on this parameter, but can be useful for
* creating the objects of the result list.
* @return a List of objects, one per row of the ResultSet. Normally all these
* will be of the same class, although it is possible to use different types.
*/
public List executeByNamedParam(Map paramMap, Map context) throws DataAccessException {
validateNamedParameters(paramMap);
Object[] parameters = NamedParameterUtils.buildValueArray(getSql(), paramMap);
RowMapper rowMapper = newRowMapper(parameters, context);
String sqlToUse = NamedParameterUtils.substituteNamedParameters(getSql(), new MapSqlParameterSource(paramMap));
return getJdbcTemplate().query(newPreparedStatementCreator(sqlToUse, parameters), rowMapper);
}
/**
* Convenient method to execute without context.
* @param paramMap parameters associated with the name specified while declaring
* the SqlParameters. Primitive parameters must be represented by their Object wrapper
* type. The ordering of parameters is not significant.
*/
public List executeByNamedParam(Map paramMap) throws DataAccessException {
return executeByNamedParam(paramMap, null);
}
/**
* Generic object finder method, used by all other findObject
methods.
* Object finder methods are like EJB entity bean finders, in that it is
* considered an error if they return more than one result.
* @return the result object, or null
if not found. Subclasses may
* choose to treat this as an error and throw an exception.
* @see org.springframework.dao.support.DataAccessUtils#uniqueResult
*/
public Object findObject(Object[] parameters, Map context) throws DataAccessException {
List results = execute(parameters, context);
return DataAccessUtils.uniqueResult(results);
}
/**
* Convenient method to find a single object without context.
*/
public Object findObject(Object[] params) throws DataAccessException {
return findObject(params, null);
}
/**
* Convenient method to find a single object given a single int parameter
* and a context.
*/
public Object findObject(int p1, Map context) throws DataAccessException {
return findObject(new Object[] {new Integer(p1)}, context);
}
/**
* Convenient method to find a single object given a single int parameter.
*/
public Object findObject(int p1) throws DataAccessException {
return findObject(p1, null);
}
/**
* Convenient method to find a single object given two int parameters
* and a context.
*/
public Object findObject(int p1, int p2, Map context) throws DataAccessException {
return findObject(new Object[] {new Integer(p1), new Integer(p2)}, context);
}
/**
* Convenient method to find a single object given two int parameters.
*/
public Object findObject(int p1, int p2) throws DataAccessException {
return findObject(p1, p2, null);
}
/**
* Convenient method to find a single object given a single long parameter
* and a context.
*/
public Object findObject(long p1, Map context) throws DataAccessException {
return findObject(new Object[] {new Long(p1)}, context);
}
/**
* Convenient method to find a single object given a single long parameter.
*/
public Object findObject(long p1) throws DataAccessException {
return findObject(p1, null);
}
/**
* Convenient method to find a single object given a single String parameter
* and a context.
*/
public Object findObject(String p1, Map context) throws DataAccessException {
return findObject(new Object[] {p1}, context);
}
/**
* Convenient method to find a single object given a single String parameter.
*/
public Object findObject(String p1) throws DataAccessException {
return findObject(p1, null);
}
/**
* Generic object finder method for named parameters.
* @param paramMap Map of parameter name to parameter object,
* matching named parameters specified in the SQL statement.
* Ordering is not significant.
* @param context contextual information passed to the callback mapRow method.
* @return a List of objects, one per row of the ResultSet. Normally all these
* will be of the same class, although it is possible to use different types.
*/
public Object findObjectByNamedParam(Map paramMap, Map context) throws DataAccessException {
List results = executeByNamedParam(paramMap, context);
return DataAccessUtils.uniqueResult(results);
}
/**
* Convenient method to execute without context.
* @param paramMap Map of parameter name to parameter object,
* matching named parameters specified in the SQL statement.
* Ordering is not significant.
*/
public Object findObjectByNamedParam(Map paramMap) throws DataAccessException {
return findObjectByNamedParam(paramMap, null);
}
//-------------------------------------------------------------------------
// Methods to be implemented by subclasses
//-------------------------------------------------------------------------
/**
* Subclasses must implement this method to extract an object per row,
* to be returned by the execute method as aggregated List.
* @param parameters parameters to the execute()
method,
* in case subclass is interested. May be null
if there
* were no parameters.
* @see #execute
*/
protected abstract RowMapper newRowMapper(Object[] parameters, Map context);
}