/*
* Copyright 2002-2018 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.Map;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.JdbcUpdateAffectedIncorrectNumberOfRowsException;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterUtils;
import org.springframework.jdbc.core.namedparam.ParsedSql;
import org.springframework.jdbc.support.KeyHolder;
Reusable operation object representing a SQL update.
This class provides a number of update
methods, analogous to the execute
methods of query objects.
This class is concrete. Although it can be subclassed (for example
to add a custom update method) it can easily be parameterized by setting
SQL and declaring parameters.
Like all RdbmsOperation
classes that ship with the Spring Framework, SqlQuery
instances are thread-safe 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.
Author: Rod Johnson, Thomas Risberg, Juergen Hoeller See Also:
/**
* Reusable operation object representing a SQL update.
*
* <p>This class provides a number of {@code update} methods,
* analogous to the {@code execute} methods of query objects.
*
* <p>This class is concrete. Although it can be subclassed (for example
* to add a custom update method) it can easily be parameterized by setting
* SQL and declaring parameters.
*
* <p>Like all {@code RdbmsOperation} classes that ship with the Spring
* Framework, {@code SqlQuery} instances are thread-safe 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.
*
* @author Rod Johnson
* @author Thomas Risberg
* @author Juergen Hoeller
* @see SqlQuery
*/
public class SqlUpdate extends SqlOperation {
Maximum number of rows the update may affect. If more are
affected, an exception will be thrown. Ignored if 0.
/**
* Maximum number of rows the update may affect. If more are
* affected, an exception will be thrown. Ignored if 0.
*/
private int maxRowsAffected = 0;
An exact number of rows that must be affected.
Ignored if 0.
/**
* An exact number of rows that must be affected.
* Ignored if 0.
*/
private int requiredRowsAffected = 0;
Constructor to allow use as a JavaBean. DataSource and SQL
must be supplied before compilation and use.
See Also: - setDataSource
- RdbmsOperation.setSql
/**
* Constructor to allow use as a JavaBean. DataSource and SQL
* must be supplied before compilation and use.
* @see #setDataSource
* @see #setSql
*/
public SqlUpdate() {
}
Constructs an update object with a given DataSource and SQL.
Params: - ds – the DataSource to use to obtain connections
- sql – the SQL statement to execute
/**
* Constructs an update object with a given DataSource and SQL.
* @param ds the DataSource to use to obtain connections
* @param sql the SQL statement to execute
*/
public SqlUpdate(DataSource ds, String sql) {
setDataSource(ds);
setSql(sql);
}
Construct an update object with a given DataSource, SQL
and anonymous parameters.
Params: - ds – the DataSource to use to obtain connections
- sql – the SQL statement to execute
- types – the SQL types of the parameters, as defined in the
java.sql.Types
class
See Also:
/**
* Construct an update object with a given DataSource, SQL
* and anonymous parameters.
* @param ds the DataSource to use to obtain connections
* @param sql the SQL statement to execute
* @param types the SQL types of the parameters, as defined in the
* {@code java.sql.Types} class
* @see java.sql.Types
*/
public SqlUpdate(DataSource ds, String sql, int[] types) {
setDataSource(ds);
setSql(sql);
setTypes(types);
}
Construct an update object with a given DataSource, SQL,
anonymous parameters and specifying the maximum number of rows
that may be affected.
Params: - ds – the DataSource to use to obtain connections
- sql – the SQL statement to execute
- types – the SQL types of the parameters, as defined in the
java.sql.Types
class - maxRowsAffected – the maximum number of rows that may
be affected by the update
See Also:
/**
* Construct an update object with a given DataSource, SQL,
* anonymous parameters and specifying the maximum number of rows
* that may be affected.
* @param ds the DataSource to use to obtain connections
* @param sql the SQL statement to execute
* @param types the SQL types of the parameters, as defined in the
* {@code java.sql.Types} class
* @param maxRowsAffected the maximum number of rows that may
* be affected by the update
* @see java.sql.Types
*/
public SqlUpdate(DataSource ds, String sql, int[] types, int maxRowsAffected) {
setDataSource(ds);
setSql(sql);
setTypes(types);
this.maxRowsAffected = maxRowsAffected;
}
Set the maximum number of rows that may be affected by this update.
The default value is 0, which does not limit the number of rows affected.
Params: - maxRowsAffected – the maximum number of rows that can be affected by
this update without this class's update method considering it an error
/**
* Set the maximum number of rows that may be affected by this update.
* The default value is 0, which does not limit the number of rows affected.
* @param maxRowsAffected the maximum number of rows that can be affected by
* this update without this class's update method considering it an error
*/
public void setMaxRowsAffected(int maxRowsAffected) {
this.maxRowsAffected = maxRowsAffected;
}
Set the exact number of rows that must be affected by this update.
The default value is 0, which allows any number of rows to be affected.
This is an alternative to setting the maximum number of rows
that may be affected.
Params: - requiredRowsAffected – the exact number of rows that must be affected
by this update without this class's update method considering it an error
/**
* Set the <i>exact</i> number of rows that must be affected by this update.
* The default value is 0, which allows any number of rows to be affected.
* <p>This is an alternative to setting the <i>maximum</i> number of rows
* that may be affected.
* @param requiredRowsAffected the exact number of rows that must be affected
* by this update without this class's update method considering it an error
*/
public void setRequiredRowsAffected(int requiredRowsAffected) {
this.requiredRowsAffected = requiredRowsAffected;
}
Check the given number of affected rows against the
specified maximum number or required number.
Params: - rowsAffected – the number of affected rows
Throws: - JdbcUpdateAffectedIncorrectNumberOfRowsException –
if the actually affected rows are out of bounds
See Also:
/**
* Check the given number of affected rows against the
* specified maximum number or required number.
* @param rowsAffected the number of affected rows
* @throws JdbcUpdateAffectedIncorrectNumberOfRowsException
* if the actually affected rows are out of bounds
* @see #setMaxRowsAffected
* @see #setRequiredRowsAffected
*/
protected void checkRowsAffected(int rowsAffected) throws JdbcUpdateAffectedIncorrectNumberOfRowsException {
if (this.maxRowsAffected > 0 && rowsAffected > this.maxRowsAffected) {
throw new JdbcUpdateAffectedIncorrectNumberOfRowsException(resolveSql(), this.maxRowsAffected, rowsAffected);
}
if (this.requiredRowsAffected > 0 && rowsAffected != this.requiredRowsAffected) {
throw new JdbcUpdateAffectedIncorrectNumberOfRowsException(resolveSql(), this.requiredRowsAffected, rowsAffected);
}
}
Generic method to execute the update given parameters.
All other update methods invoke this method.
Params: - params – array of parameters objects
Returns: the number of rows affected by the update
/**
* Generic method to execute the update given parameters.
* All other update methods invoke this method.
* @param params array of parameters objects
* @return the number of rows affected by the update
*/
public int update(Object... params) throws DataAccessException {
validateParameters(params);
int rowsAffected = getJdbcTemplate().update(newPreparedStatementCreator(params));
checkRowsAffected(rowsAffected);
return rowsAffected;
}
Method to execute the update given arguments and
retrieve the generated keys using a KeyHolder.
Params: - params – array of parameter objects
- generatedKeyHolder – the KeyHolder that will hold the generated keys
Returns: the number of rows affected by the update
/**
* Method to execute the update given arguments and
* retrieve the generated keys using a KeyHolder.
* @param params array of parameter objects
* @param generatedKeyHolder the KeyHolder that will hold the generated keys
* @return the number of rows affected by the update
*/
public int update(Object[] params, KeyHolder generatedKeyHolder) throws DataAccessException {
if (!isReturnGeneratedKeys() && getGeneratedKeysColumnNames() == null) {
throw new InvalidDataAccessApiUsageException(
"The update method taking a KeyHolder should only be used when generated keys have " +
"been configured by calling either 'setReturnGeneratedKeys' or " +
"'setGeneratedKeysColumnNames'.");
}
validateParameters(params);
int rowsAffected = getJdbcTemplate().update(newPreparedStatementCreator(params), generatedKeyHolder);
checkRowsAffected(rowsAffected);
return rowsAffected;
}
Convenience method to execute an update with no parameters.
/**
* Convenience method to execute an update with no parameters.
*/
public int update() throws DataAccessException {
return update(new Object[0]);
}
Convenient method to execute an update given one int arg.
/**
* Convenient method to execute an update given one int arg.
*/
public int update(int p1) throws DataAccessException {
return update(new Object[] {p1});
}
Convenient method to execute an update given two int args.
/**
* Convenient method to execute an update given two int args.
*/
public int update(int p1, int p2) throws DataAccessException {
return update(new Object[] {p1, p2});
}
Convenient method to execute an update given one long arg.
/**
* Convenient method to execute an update given one long arg.
*/
public int update(long p1) throws DataAccessException {
return update(new Object[] {p1});
}
Convenient method to execute an update given two long args.
/**
* Convenient method to execute an update given two long args.
*/
public int update(long p1, long p2) throws DataAccessException {
return update(new Object[] {p1, p2});
}
Convenient method to execute an update given one String arg.
/**
* Convenient method to execute an update given one String arg.
*/
public int update(String p) throws DataAccessException {
return update(new Object[] {p});
}
Convenient method to execute an update given two String args.
/**
* Convenient method to execute an update given two String args.
*/
public int update(String p1, String p2) throws DataAccessException {
return update(new Object[] {p1, p2});
}
Generic method to execute the update given named parameters.
All other update methods invoke this method.
Params: - paramMap – a Map of parameter name to parameter object,
matching named parameters specified in the SQL statement
Returns: the number of rows affected by the update
/**
* Generic method to execute the update given named parameters.
* All other update methods invoke this method.
* @param paramMap a Map of parameter name to parameter object,
* matching named parameters specified in the SQL statement
* @return the number of rows affected by the update
*/
public int updateByNamedParam(Map<String, ?> paramMap) throws DataAccessException {
validateNamedParameters(paramMap);
ParsedSql parsedSql = getParsedSql();
MapSqlParameterSource paramSource = new MapSqlParameterSource(paramMap);
String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource);
Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, getDeclaredParameters());
int rowsAffected = getJdbcTemplate().update(newPreparedStatementCreator(sqlToUse, params));
checkRowsAffected(rowsAffected);
return rowsAffected;
}
Method to execute the update given arguments and
retrieve the generated keys using a KeyHolder.
Params: - paramMap – a Map of parameter name to parameter object,
matching named parameters specified in the SQL statement
- generatedKeyHolder – the KeyHolder that will hold the generated keys
Returns: the number of rows affected by the update
/**
* Method to execute the update given arguments and
* retrieve the generated keys using a KeyHolder.
* @param paramMap a Map of parameter name to parameter object,
* matching named parameters specified in the SQL statement
* @param generatedKeyHolder the KeyHolder that will hold the generated keys
* @return the number of rows affected by the update
*/
public int updateByNamedParam(Map<String, ?> paramMap, KeyHolder generatedKeyHolder) throws DataAccessException {
validateNamedParameters(paramMap);
ParsedSql parsedSql = getParsedSql();
MapSqlParameterSource paramSource = new MapSqlParameterSource(paramMap);
String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource);
Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, getDeclaredParameters());
int rowsAffected = getJdbcTemplate().update(newPreparedStatementCreator(sqlToUse, params), generatedKeyHolder);
checkRowsAffected(rowsAffected);
return rowsAffected;
}
}