下面列出了org.springframework.jdbc.core.ColumnMapRowMapper#org.springframework.jdbc.core.SqlParameter 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Validate the parameters passed to an execute method based on declared parameters.
* Subclasses should invoke this method before every {@code executeQuery()}
* or {@code update()} method.
* @param parameters parameters supplied (may be {@code null})
* @throws InvalidDataAccessApiUsageException if the parameters are invalid
*/
protected void validateParameters(@Nullable Object[] parameters) throws InvalidDataAccessApiUsageException {
checkCompiled();
int declaredInParameters = 0;
for (SqlParameter param : this.declaredParameters) {
if (param.isInputValueProvided()) {
if (!supportsLobParameters() &&
(param.getSqlType() == Types.BLOB || param.getSqlType() == Types.CLOB)) {
throw new InvalidDataAccessApiUsageException(
"BLOB or CLOB parameters are not allowed for this kind of operation");
}
declaredInParameters++;
}
}
validateParameterCount((parameters != null ? parameters.length : 0), declaredInParameters);
}
/**
* Validate the named parameters passed to an execute method based on declared parameters.
* Subclasses should invoke this method before every {@code executeQuery()} or
* {@code update()} method.
* @param parameters parameter Map supplied (may be {@code null})
* @throws InvalidDataAccessApiUsageException if the parameters are invalid
*/
protected void validateNamedParameters(@Nullable Map<String, ?> parameters) throws InvalidDataAccessApiUsageException {
checkCompiled();
Map<String, ?> paramsToUse = (parameters != null ? parameters : Collections.<String, Object> emptyMap());
int declaredInParameters = 0;
for (SqlParameter param : this.declaredParameters) {
if (param.isInputValueProvided()) {
if (!supportsLobParameters() &&
(param.getSqlType() == Types.BLOB || param.getSqlType() == Types.CLOB)) {
throw new InvalidDataAccessApiUsageException(
"BLOB or CLOB parameters are not allowed for this kind of operation");
}
if (param.getName() != null && !paramsToUse.containsKey(param.getName())) {
throw new InvalidDataAccessApiUsageException("The parameter named '" + param.getName() +
"' was not among the parameters supplied: " + paramsToUse.keySet());
}
declaredInParameters++;
}
}
validateParameterCount(paramsToUse.size(), declaredInParameters);
}
/**
* Method to perform the actual compilation. Subclasses can override this template method to perform
* their own compilation. Invoked after this base class's compilation is complete.
*/
protected void compileInternal() {
this.callMetaDataContext.initializeMetaData(getJdbcTemplate().getDataSource());
// iterate over the declared RowMappers and register the corresponding SqlParameter
for (Map.Entry<String, RowMapper<?>> entry : this.declaredRowMappers.entrySet()) {
SqlParameter resultSetParameter =
this.callMetaDataContext.createReturnResultSetParameter(entry.getKey(), entry.getValue());
this.declaredParameters.add(resultSetParameter);
}
this.callMetaDataContext.processParameters(this.declaredParameters);
this.callString = this.callMetaDataContext.createCallString();
if (logger.isDebugEnabled()) {
logger.debug("Compiled stored procedure. Call string is [" + this.callString + "]");
}
this.callableStatementFactory =
new CallableStatementCreatorFactory(getCallString(), this.callMetaDataContext.getCallParameters());
this.callableStatementFactory.setNativeJdbcExtractor(getJdbcTemplate().getNativeJdbcExtractor());
onCompileInternal();
}
/**
* Validate the named parameters passed to an execute method based on declared parameters.
* Subclasses should invoke this method before every {@code executeQuery()} or
* {@code update()} method.
* @param parameters parameter Map supplied (may be {@code null})
* @throws InvalidDataAccessApiUsageException if the parameters are invalid
*/
protected void validateNamedParameters(Map<String, ?> parameters) throws InvalidDataAccessApiUsageException {
checkCompiled();
Map<String, ?> paramsToUse = (parameters != null ? parameters : Collections.<String, Object> emptyMap());
int declaredInParameters = 0;
for (SqlParameter param : this.declaredParameters) {
if (param.isInputValueProvided()) {
if (!supportsLobParameters() &&
(param.getSqlType() == Types.BLOB || param.getSqlType() == Types.CLOB)) {
throw new InvalidDataAccessApiUsageException(
"BLOB or CLOB parameters are not allowed for this kind of operation");
}
if (param.getName() != null && !paramsToUse.containsKey(param.getName())) {
throw new InvalidDataAccessApiUsageException("The parameter named '" + param.getName() +
"' was not among the parameters supplied: " + paramsToUse.keySet());
}
declaredInParameters++;
}
}
validateParameterCount(paramsToUse.size(), declaredInParameters);
}
/**
* Validate the parameters passed to an execute method based on declared parameters.
* Subclasses should invoke this method before every {@code executeQuery()}
* or {@code update()} method.
* @param parameters parameters supplied (may be {@code null})
* @throws InvalidDataAccessApiUsageException if the parameters are invalid
*/
protected void validateParameters(Object[] parameters) throws InvalidDataAccessApiUsageException {
checkCompiled();
int declaredInParameters = 0;
for (SqlParameter param : this.declaredParameters) {
if (param.isInputValueProvided()) {
if (!supportsLobParameters() &&
(param.getSqlType() == Types.BLOB || param.getSqlType() == Types.CLOB)) {
throw new InvalidDataAccessApiUsageException(
"BLOB or CLOB parameters are not allowed for this kind of operation");
}
declaredInParameters++;
}
}
validateParameterCount((parameters != null ? parameters.length : 0), declaredInParameters);
}
@Test
public void testQueryWithMissingMapParams() {
MappingSqlQuery<Integer> query = new MappingSqlQuery<Integer>() {
@Override
protected Integer mapRow(ResultSet rs, int rownum) throws SQLException {
return rs.getInt(1);
}
};
query.setDataSource(dataSource);
query.setSql(SELECT_ID_WHERE);
query.declareParameter(new SqlParameter(COLUMN_NAMES[0], COLUMN_TYPES[0]));
query.declareParameter(new SqlParameter(COLUMN_NAMES[1], COLUMN_TYPES[1]));
query.compile();
assertThatExceptionOfType(InvalidDataAccessApiUsageException.class).isThrownBy(() ->
query.executeByNamedParam(Collections.singletonMap(COLUMN_NAMES[0], "value")));
}
/**
* Validate the named parameters passed to an execute method based on declared parameters.
* Subclasses should invoke this method before every {@code executeQuery()} or
* {@code update()} method.
* @param parameters parameter Map supplied. May be {@code null}.
* @throws InvalidDataAccessApiUsageException if the parameters are invalid
*/
protected void validateNamedParameters(Map<String, ?> parameters) throws InvalidDataAccessApiUsageException {
checkCompiled();
Map<String, ?> paramsToUse = (parameters != null ? parameters : Collections.<String, Object> emptyMap());
int declaredInParameters = 0;
for (SqlParameter param : this.declaredParameters) {
if (param.isInputValueProvided()) {
if (!supportsLobParameters() &&
(param.getSqlType() == Types.BLOB || param.getSqlType() == Types.CLOB)) {
throw new InvalidDataAccessApiUsageException(
"BLOB or CLOB parameters are not allowed for this kind of operation");
}
if (param.getName() != null && !paramsToUse.containsKey(param.getName())) {
throw new InvalidDataAccessApiUsageException("The parameter named '" + param.getName() +
"' was not among the parameters supplied: " + paramsToUse.keySet());
}
declaredInParameters++;
}
}
validateParameterCount(paramsToUse.size(), declaredInParameters);
}
/**
* Validate the parameters passed to an execute method based on declared parameters.
* Subclasses should invoke this method before every {@code executeQuery()}
* or {@code update()} method.
* @param parameters parameters supplied (may be {@code null})
* @throws InvalidDataAccessApiUsageException if the parameters are invalid
*/
protected void validateParameters(Object[] parameters) throws InvalidDataAccessApiUsageException {
checkCompiled();
int declaredInParameters = 0;
for (SqlParameter param : this.declaredParameters) {
if (param.isInputValueProvided()) {
if (!supportsLobParameters() &&
(param.getSqlType() == Types.BLOB || param.getSqlType() == Types.CLOB)) {
throw new InvalidDataAccessApiUsageException(
"BLOB or CLOB parameters are not allowed for this kind of operation");
}
declaredInParameters++;
}
}
validateParameterCount((parameters != null ? parameters.length : 0), declaredInParameters);
}
/**
* Delegate method to perform the actual compilation.
* <p>Subclasses can override this template method to perform their own compilation.
* Invoked after this base class's compilation is complete.
*/
protected void compileInternal() {
this.callMetaDataContext.initializeMetaData(getJdbcTemplate().getDataSource());
// Iterate over the declared RowMappers and register the corresponding SqlParameter
for (Map.Entry<String, RowMapper<?>> entry : this.declaredRowMappers.entrySet()) {
SqlParameter resultSetParameter =
this.callMetaDataContext.createReturnResultSetParameter(entry.getKey(), entry.getValue());
this.declaredParameters.add(resultSetParameter);
}
this.callMetaDataContext.processParameters(this.declaredParameters);
this.callString = this.callMetaDataContext.createCallString();
if (logger.isDebugEnabled()) {
logger.debug("Compiled stored procedure. Call string is [" + this.callString + "]");
}
this.callableStatementFactory =
new CallableStatementCreatorFactory(getCallString(), this.callMetaDataContext.getCallParameters());
this.callableStatementFactory.setNativeJdbcExtractor(getJdbcTemplate().getNativeJdbcExtractor());
onCompileInternal();
}
/**
* Delegate method to perform the actual compilation.
* <p>Subclasses can override this template method to perform their own compilation.
* Invoked after this base class's compilation is complete.
*/
protected void compileInternal() {
this.callMetaDataContext.initializeMetaData(getJdbcTemplate().getDataSource());
// Iterate over the declared RowMappers and register the corresponding SqlParameter
for (Map.Entry<String, RowMapper<?>> entry : this.declaredRowMappers.entrySet()) {
SqlParameter resultSetParameter =
this.callMetaDataContext.createReturnResultSetParameter(entry.getKey(), entry.getValue());
this.declaredParameters.add(resultSetParameter);
}
this.callMetaDataContext.processParameters(this.declaredParameters);
this.callString = this.callMetaDataContext.createCallString();
if (logger.isDebugEnabled()) {
logger.debug("Compiled stored procedure. Call string is [" + this.callString + "]");
}
this.callableStatementFactory =
new CallableStatementCreatorFactory(getCallString(), this.callMetaDataContext.getCallParameters());
this.callableStatementFactory.setNativeJdbcExtractor(getJdbcTemplate().getNativeJdbcExtractor());
onCompileInternal();
}
@Test
public void testQueryWithoutEnoughParams() {
MappingSqlQuery<Integer> query = new MappingSqlQuery<Integer>() {
@Override
protected Integer mapRow(ResultSet rs, int rownum) throws SQLException {
return rs.getInt(1);
}
};
query.setDataSource(dataSource);
query.setSql(SELECT_ID_WHERE);
query.declareParameter(new SqlParameter(COLUMN_NAMES[0], COLUMN_TYPES[0]));
query.declareParameter(new SqlParameter(COLUMN_NAMES[1], COLUMN_TYPES[1]));
query.compile();
thrown.expect(InvalidDataAccessApiUsageException.class);
query.execute();
}
/**
* Validate the parameters passed to an execute method based on declared parameters.
* Subclasses should invoke this method before every {@code executeQuery()}
* or {@code update()} method.
* @param parameters parameters supplied (may be {@code null})
* @throws InvalidDataAccessApiUsageException if the parameters are invalid
*/
protected void validateParameters(@Nullable Object[] parameters) throws InvalidDataAccessApiUsageException {
checkCompiled();
int declaredInParameters = 0;
for (SqlParameter param : this.declaredParameters) {
if (param.isInputValueProvided()) {
if (!supportsLobParameters() &&
(param.getSqlType() == Types.BLOB || param.getSqlType() == Types.CLOB)) {
throw new InvalidDataAccessApiUsageException(
"BLOB or CLOB parameters are not allowed for this kind of operation");
}
declaredInParameters++;
}
}
validateParameterCount((parameters != null ? parameters.length : 0), declaredInParameters);
}
@Override
public int update(
String sql, SqlParameterSource paramSource, KeyHolder generatedKeyHolder, String[] keyColumnNames)
throws DataAccessException {
ParsedSql parsedSql = getParsedSql(sql);
String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource);
Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null);
List<SqlParameter> declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql, paramSource);
PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse, declaredParameters);
if (keyColumnNames != null) {
pscf.setGeneratedKeysColumnNames(keyColumnNames);
}
else {
pscf.setReturnGeneratedKeys(true);
}
return getJdbcOperations().update(pscf.newPreparedStatementCreator(params), generatedKeyHolder);
}
public Map<String, ?> matchInParameterValuesWithCallParameters(Object[] parameterValues) {
Map<String, Object> matchedParameters = new HashMap<String, Object>(parameterValues.length);
int i = 0;
for (SqlParameter parameter : this.callParameters) {
if (parameter.isInputValueProvided()) {
String parameterName = parameter.getName();
matchedParameters.put(parameterName, parameterValues[i++]);
}
}
return matchedParameters;
}
/**
* Add a declared parameter to the list of parameters for the call.
* Only parameters declared as {@code SqlParameter} and {@code SqlInOutParameter}
* will be used to provide input values. This is different from the {@code StoredProcedure} class
* which for backwards compatibility reasons allows input values to be provided for parameters declared
* as {@code SqlOutParameter}.
* @param parameter the {@link SqlParameter} to add
*/
public void addDeclaredParameter(SqlParameter parameter) {
Assert.notNull(parameter, "The supplied parameter must not be null");
if (!StringUtils.hasText(parameter.getName())) {
throw new InvalidDataAccessApiUsageException(
"You must specify a parameter name when declaring parameters for \"" + getProcedureName() + "\"");
}
this.declaredParameters.add(parameter);
if (logger.isDebugEnabled()) {
logger.debug("Added declared parameter for [" + getProcedureName() + "]: " + parameter.getName());
}
}
private PreparedStatement getPreparedStatement(String sql, @Nullable Map<String, ?> parameters, boolean returnKeys) throws SQLException {
SqlParameterSource paramSource = new MapSqlParameterSource(parameters);
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(sql);
String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource);
List<SqlParameter> declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql, paramSource);
Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null);
PreparedStatementCreatorFactory psCreatorFactory = new PreparedStatementCreatorFactory(sqlToUse, declaredParameters);
psCreatorFactory.setReturnGeneratedKeys(returnKeys);
PreparedStatementCreator psCreator = psCreatorFactory.newPreparedStatementCreator(params);
PreparedStatement preparedStatement = psCreator.createPreparedStatement(connection);
logger.debug(preparedStatement.unwrap(PreparedStatement.class).toString());
return preparedStatement;
}
/**
* 引自NamedParameterJdbcTemplate
* @param sql
* @param paramSource
* @return PreparedStatementCreator
*/
private CallableStatementCreator getCallableStatementCreator(String sql, Map<String,Object> paramMap , String[] outParam) {
SqlParameterSource paramSource = new MapSqlParameterSource(paramMap);
ParsedSqlBean parsedSqlBean = getParsedSqlBean(sql);
parsedSqlBean.setOutParam(outParam);
String sqlToUse = ProcedureParameterUtils.substituteNamedParameters(parsedSqlBean, paramSource);
List<SqlParameter> declaredParameters = ProcedureParameterUtils.buildSqlParameterList(parsedSqlBean, paramSource);
CallableStatementCreatorFactory cscf = new CallableStatementCreatorFactory(sqlToUse, declaredParameters);
return cscf.newCallableStatementCreator(paramMap);
}
private void recurseParentChange(final String folderId, final String newParentId) {
getJdbcTemplate().call(new CallableStatementCreator() {
public CallableStatement createCallableStatement(Connection con) throws SQLException {
CallableStatement c = con.prepareCall("{ call recurse_folder_parent_change(?,?) }");
c.setString(1, folderId);
c.setString(2, newParentId);
return c;
}
}, new ArrayList<SqlParameter>());
}
/**
* Convert a Map of named parameter values to a corresponding array.
* @param parsedSql the parsed SQL statement
* @param paramSource the source for named parameters
* @param declaredParams the List of declared SqlParameter objects
* (may be {@code null}). If specified, the parameter metadata will
* be built into the value array in the form of SqlParameterValue objects.
* @return the array of values
*/
public static Object[] buildValueArray(
ParsedSql parsedSql, SqlParameterSource paramSource, @Nullable List<SqlParameter> declaredParams) {
Object[] paramArray = new Object[parsedSql.getTotalParameterCount()];
if (parsedSql.getNamedParameterCount() > 0 && parsedSql.getUnnamedParameterCount() > 0) {
throw new InvalidDataAccessApiUsageException(
"Not allowed to mix named and traditional ? placeholders. You have " +
parsedSql.getNamedParameterCount() + " named parameter(s) and " +
parsedSql.getUnnamedParameterCount() + " traditional placeholder(s) in statement: " +
parsedSql.getOriginalSql());
}
List<String> paramNames = parsedSql.getParameterNames();
for (int i = 0; i < paramNames.size(); i++) {
String paramName = paramNames.get(i);
try {
Object value = paramSource.getValue(paramName);
SqlParameter param = findParameter(declaredParams, paramName, i);
paramArray[i] = (param != null ? new SqlParameterValue(param, value) : value);
}
catch (IllegalArgumentException ex) {
throw new InvalidDataAccessApiUsageException(
"No value supplied for the SQL parameter '" + paramName + "': " + ex.getMessage());
}
}
return paramArray;
}
@Test
public void testListCustomersString() throws SQLException {
given(resultSet.next()).willReturn(true, true, false);
given(resultSet.getInt("id")).willReturn(1, 2);
given(resultSet.getString("forename")).willReturn("rod", "dave");
class CustomerQuery extends MappingSqlQuery<Customer> {
public CustomerQuery(DataSource ds) {
super(ds, SELECT_ID_FORENAME_WHERE);
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
@Override
protected Customer mapRow(ResultSet rs, int rownum) throws SQLException {
Customer cust = new Customer();
cust.setId(rs.getInt(COLUMN_NAMES[0]));
cust.setForename(rs.getString(COLUMN_NAMES[1]));
return cust;
}
}
CustomerQuery query = new CustomerQuery(dataSource);
List<Customer> list = query.execute("one");
assertTrue("2 results in list", list.size() == 2);
assertThat(list.get(0).getForename(), is("rod"));
assertThat(list.get(1).getForename(), is("dave"));
verify(preparedStatement).setString(1, "one");
verify(connection).prepareStatement(SELECT_ID_FORENAME_WHERE);
verify(resultSet).close();
verify(preparedStatement).close();
verify(connection).close();
}
@Override
public SqlParameter createDefaultOutParameter(String parameterName, CallParameterMetaData meta) {
if (meta.getSqlType() == Types.OTHER && REF_CURSOR_NAME.equals(meta.getTypeName())) {
return new SqlOutParameter(parameterName, getRefCursorSqlType(), new ColumnMapRowMapper());
}
else {
return super.createDefaultOutParameter(parameterName, meta);
}
}
@Override
public SqlParameter createDefaultOutParameter(String parameterName, CallParameterMetaData meta) {
if (meta.getSqlType() == Types.OTHER && REF_CURSOR_NAME.equals(meta.getTypeName())) {
return new SqlOutParameter(parameterName, getRefCursorSqlType(), new ColumnMapRowMapper());
}
else {
return super.createDefaultOutParameter(parameterName, meta);
}
}
@Test
public void testFindTooManyCustomers() throws SQLException {
given(resultSet.next()).willReturn(true, true, false);
given(resultSet.getInt("id")).willReturn(1, 2);
given(resultSet.getString("forename")).willReturn("rod", "rod");
class CustomerQuery extends MappingSqlQuery<Customer> {
public CustomerQuery(DataSource ds) {
super(ds, SELECT_ID_FORENAME_WHERE);
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
@Override
protected Customer mapRow(ResultSet rs, int rownum) throws SQLException {
Customer cust = new Customer();
cust.setId(rs.getInt(COLUMN_NAMES[0]));
cust.setForename(rs.getString(COLUMN_NAMES[1]));
return cust;
}
public Customer findCustomer(String id) {
return findObject(id);
}
}
CustomerQuery query = new CustomerQuery(dataSource);
thrown.expect(IncorrectResultSizeDataAccessException.class);
try {
query.findCustomer("rod");
}
finally {
verify(preparedStatement).setString(1, "rod");
verify(connection).prepareStatement(SELECT_ID_FORENAME_WHERE);
verify(resultSet).close();
verify(preparedStatement).close();
verify(connection).close();
}
}
/**
* Build a PreparedStatementCreator based on the given SQL and named parameters.
* <p>Note: Not used for the {@code update} variant with generated key handling.
* @param sql SQL to execute
* @param paramSource container of arguments to bind
* @return the corresponding PreparedStatementCreator
*/
protected PreparedStatementCreator getPreparedStatementCreator(String sql, SqlParameterSource paramSource) {
ParsedSql parsedSql = getParsedSql(sql);
String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource);
Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null);
List<SqlParameter> declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql, paramSource);
PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse, declaredParameters);
return pscf.newPreparedStatementCreator(params);
}
/**
* Build a PreparedStatementCreator based on the given SQL and named parameters.
* <p>Note: Not used for the {@code update} variant with generated key handling.
* @param sql SQL to execute
* @param paramSource container of arguments to bind
* @return the corresponding PreparedStatementCreator
*/
protected PreparedStatementCreator getPreparedStatementCreator(String sql, SqlParameterSource paramSource) {
ParsedSql parsedSql = getParsedSql(sql);
String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource);
Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null);
List<SqlParameter> declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql, paramSource);
PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse, declaredParameters);
return pscf.newPreparedStatementCreator(params);
}
@Test
public void testUnnamedParameterDeclarationWithNamedParameterQuery()
throws SQLException {
class CustomerQuery extends MappingSqlQuery<Customer> {
public CustomerQuery(DataSource ds) {
super(ds, SELECT_ID_FORENAME_WHERE);
setResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE);
declareParameter(new SqlParameter(Types.NUMERIC));
compile();
}
@Override
protected Customer mapRow(ResultSet rs, int rownum) throws SQLException {
Customer cust = new Customer();
cust.setId(rs.getInt(COLUMN_NAMES[0]));
cust.setForename(rs.getString(COLUMN_NAMES[1]));
return cust;
}
public Customer findCustomer(int id) {
Map<String, Integer> params = new HashMap<String, Integer>();
params.put("id", id);
return executeByNamedParam(params).get(0);
}
}
// Query should not succeed since parameter declaration did not specify parameter name
CustomerQuery query = new CustomerQuery(dataSource);
thrown.expect(InvalidDataAccessApiUsageException.class);
query.findCustomer(1);
}
@Test
public void testMatchParameterValuesAndSqlInOutParameters() throws Exception {
final String TABLE = "customers";
final String USER = "me";
given(databaseMetaData.getDatabaseProductName()).willReturn("MyDB");
given(databaseMetaData.getUserName()).willReturn(USER);
given(databaseMetaData.storesLowerCaseIdentifiers()).willReturn(true);
List<SqlParameter> parameters = new ArrayList<SqlParameter>();
parameters.add(new SqlParameter("id", Types.NUMERIC));
parameters.add(new SqlInOutParameter("name", Types.NUMERIC));
parameters.add(new SqlOutParameter("customer_no", Types.NUMERIC));
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
parameterSource.addValue("id", 1);
parameterSource.addValue("name", "Sven");
parameterSource.addValue("customer_no", "12345XYZ");
context.setProcedureName(TABLE);
context.initializeMetaData(dataSource);
context.processParameters(parameters);
Map<String, Object> inParameters = context.matchInParameterValuesWithCallParameters(parameterSource);
assertEquals("Wrong number of matched in parameter values", 2, inParameters.size());
assertTrue("in parameter value missing", inParameters.containsKey("id"));
assertTrue("in out parameter value missing", inParameters.containsKey("name"));
assertTrue("out parameter value matched", !inParameters.containsKey("customer_no"));
List<String> names = context.getOutParameterNames();
assertEquals("Wrong number of out parameters", 2, names.size());
List<SqlParameter> callParameters = context.getCallParameters();
assertEquals("Wrong number of call parameters", 3, callParameters.size());
}
@Override
public SimpleJdbcCall declareParameters(SqlParameter... sqlParameters) {
for (SqlParameter sqlParameter : sqlParameters) {
if (sqlParameter != null) {
addDeclaredParameter(sqlParameter);
}
}
return this;
}
/**
* Add a declared parameter to the list of parameters for the call.
* <p>Only parameters declared as {@code SqlParameter} and {@code SqlInOutParameter} will
* be used to provide input values. This is different from the {@code StoredProcedure}
* class which - for backwards compatibility reasons - allows input values to be provided
* for parameters declared as {@code SqlOutParameter}.
* @param parameter the {@link SqlParameter} to add
*/
public void addDeclaredParameter(SqlParameter parameter) {
Assert.notNull(parameter, "The supplied parameter must not be null");
if (!StringUtils.hasText(parameter.getName())) {
throw new InvalidDataAccessApiUsageException(
"You must specify a parameter name when declaring parameters for \"" + getProcedureName() + "\"");
}
this.declaredParameters.add(parameter);
if (logger.isDebugEnabled()) {
logger.debug("Added declared parameter for [" + getProcedureName() + "]: " + parameter.getName());
}
}
public IntIntUpdater() {
setSql(UPDATE_INT_INT);
setDataSource(dataSource);
declareParameter(new SqlParameter(Types.NUMERIC));
declareParameter(new SqlParameter(Types.NUMERIC));
compile();
}