Skip to content

Commit 2b4004d

Browse files
committed
Consistent Map<String, ?> declarations and use of LinkedHashMap for incoming JDBC operation parameters
Issue: SPR-12462
1 parent 223d849 commit 2b4004d

File tree

9 files changed

+203
-196
lines changed

9 files changed

+203
-196
lines changed

spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -65,28 +65,25 @@ public class CallMetaDataContext {
6565
/** List of SqlParameter objects to be used in call execution */
6666
private List<SqlParameter> callParameters = new ArrayList<SqlParameter>();
6767

68-
/** Default name to use for the return value in the output map */
69-
private String defaultFunctionReturnName = "return";
70-
7168
/** Actual name to use for the return value in the output map */
72-
private String actualFunctionReturnName = null;
69+
private String actualFunctionReturnName;
7370

7471
/** Set of in parameter names to exclude use for any not listed */
7572
private Set<String> limitedInParameterNames = new HashSet<String>();
7673

7774
/** List of SqlParameter names for out parameters */
7875
private List<String> outParameterNames = new ArrayList<String>();
7976

80-
/** should we access call parameter meta data info or not */
81-
private boolean accessCallParameterMetaData = true;
77+
/** Indicates whether this is a procedure or a function **/
78+
private boolean function = false;
8279

83-
/** indicates whether this is a procedure or a function **/
84-
private boolean function;
80+
/** Indicates whether this procedure's return value should be included **/
81+
private boolean returnValueRequired = false;
8582

86-
/** indicates whether this procedure's return value should be included **/
87-
private boolean returnValueRequired;
83+
/** Should we access call parameter meta data info or not */
84+
private boolean accessCallParameterMetaData = true;
8885

89-
/** the provider of call meta data */
86+
/** The provider of call meta data */
9087
private CallMetaDataProvider metaDataProvider;
9188

9289

@@ -101,7 +98,7 @@ public void setFunctionReturnName(String functionReturnName) {
10198
* Get the name used for the return value of the function.
10299
*/
103100
public String getFunctionReturnName() {
104-
return this.actualFunctionReturnName != null ? this.actualFunctionReturnName : this.defaultFunctionReturnName;
101+
return (this.actualFunctionReturnName != null ? this.actualFunctionReturnName : "return");
105102
}
106103

107104
/**
@@ -571,15 +568,15 @@ public String createCallString() {
571568
// and the catalog name since the cataog is used for the package name
572569
if (this.metaDataProvider.isSupportsSchemasInProcedureCalls() &&
573570
!this.metaDataProvider.isSupportsCatalogsInProcedureCalls()) {
574-
schemaNameToUse = this.metaDataProvider.catalogNameToUse(this.getCatalogName());
575-
catalogNameToUse = this.metaDataProvider.schemaNameToUse(this.getSchemaName());
571+
schemaNameToUse = this.metaDataProvider.catalogNameToUse(getCatalogName());
572+
catalogNameToUse = this.metaDataProvider.schemaNameToUse(getSchemaName());
576573
}
577574
else {
578-
catalogNameToUse = this.metaDataProvider.catalogNameToUse(this.getCatalogName());
579-
schemaNameToUse = this.metaDataProvider.schemaNameToUse(this.getSchemaName());
575+
catalogNameToUse = this.metaDataProvider.catalogNameToUse(getCatalogName());
576+
schemaNameToUse = this.metaDataProvider.schemaNameToUse(getSchemaName());
580577
}
581-
String procedureNameToUse = this.metaDataProvider.procedureNameToUse(this.getProcedureName());
582-
if (this.isFunction() || this.isReturnValueRequired()) {
578+
String procedureNameToUse = this.metaDataProvider.procedureNameToUse(getProcedureName());
579+
if (isFunction() || isReturnValueRequired()) {
583580
callString = "{? = call " +
584581
(StringUtils.hasLength(catalogNameToUse) ? catalogNameToUse + "." : "") +
585582
(StringUtils.hasLength(schemaNameToUse) ? schemaNameToUse + "." : "") +

spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataContext.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
package org.springframework.jdbc.core.metadata;
1818

1919
import java.util.ArrayList;
20-
import java.util.HashMap;
21-
import java.util.HashSet;
20+
import java.util.LinkedHashMap;
21+
import java.util.LinkedHashSet;
2222
import java.util.List;
2323
import java.util.Map;
2424
import java.util.Set;
@@ -39,6 +39,7 @@
3939
* and execution of operations on a database table.
4040
*
4141
* @author Thomas Risberg
42+
* @author Juergen Hoeller
4243
* @since 2.5
4344
*/
4445
public class TableMetaDataContext {
@@ -217,7 +218,7 @@ protected List<String> reconcileColumnsToUse(List<String> declaredColumns, Strin
217218
if (declaredColumns.size() > 0) {
218219
return new ArrayList<String>(declaredColumns);
219220
}
220-
Set<String> keys = new HashSet<String>(generatedKeyNames.length);
221+
Set<String> keys = new LinkedHashSet<String>(generatedKeyNames.length);
221222
for (String key : generatedKeyNames) {
222223
keys.add(key.toUpperCase());
223224
}
@@ -274,9 +275,9 @@ public List<Object> matchInParameterValuesWithInsertColumns(SqlParameterSource p
274275
* Match the provided column names and values with the list of columns used.
275276
* @param inParameters the parameter names and values
276277
*/
277-
public List<Object> matchInParameterValuesWithInsertColumns(Map<String, Object> inParameters) {
278+
public List<Object> matchInParameterValuesWithInsertColumns(Map<String, ?> inParameters) {
278279
List<Object> values = new ArrayList<Object>();
279-
Map<String, Object> source = new HashMap<String, Object>();
280+
Map<String, Object> source = new LinkedHashMap<String, Object>(inParameters.size());
280281
for (String key : inParameters.keySet()) {
281282
source.put(key.toLowerCase(), inParameters.get(key));
282283
}
@@ -292,7 +293,7 @@ public List<Object> matchInParameterValuesWithInsertColumns(Map<String, Object>
292293
* @return the insert string to be used
293294
*/
294295
public String createInsertString(String... generatedKeyNames) {
295-
HashSet<String> keys = new HashSet<String>(generatedKeyNames.length);
296+
Set<String> keys = new LinkedHashSet<String>(generatedKeyNames.length);
296297
for (String key : generatedKeyNames) {
297298
keys.add(key.toUpperCase());
298299
}
@@ -342,7 +343,8 @@ public String createInsertString(String... generatedKeyNames) {
342343
public int[] createInsertTypes() {
343344
int[] types = new int[this.getTableColumns().size()];
344345
List<TableParameterMetaData> parameters = this.metaDataProvider.getTableParameterMetaData();
345-
Map<String, TableParameterMetaData> parameterMap = new HashMap<String, TableParameterMetaData>(parameters.size());
346+
Map<String, TableParameterMetaData> parameterMap =
347+
new LinkedHashMap<String, TableParameterMetaData>(parameters.size());
346348
for (TableParameterMetaData tpmd : parameters) {
347349
parameterMap.put(tpmd.getParameterName().toUpperCase(), tpmd);
348350
}

spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/MapSqlParameterSource.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
1717
package org.springframework.jdbc.core.namedparam;
1818

1919
import java.util.Collections;
20-
import java.util.HashMap;
20+
import java.util.LinkedHashMap;
2121
import java.util.Map;
2222

2323
import org.springframework.jdbc.core.SqlParameterValue;
@@ -29,8 +29,8 @@
2929
* <p>This class is intended for passing in a simple Map of parameter values
3030
* to the methods of the {@link NamedParameterJdbcTemplate} class.
3131
*
32-
* <p>The {@code addValue} methods on this class will make adding several
33-
* values easier. The methods return a reference to the {@link MapSqlParameterSource}
32+
* <p>The {@code addValue} methods on this class will make adding several values
33+
* easier. The methods return a reference to the {@link MapSqlParameterSource}
3434
* itself, so you can chain several method calls together within a single statement.
3535
*
3636
* @author Thomas Risberg
@@ -43,7 +43,7 @@
4343
*/
4444
public class MapSqlParameterSource extends AbstractSqlParameterSource {
4545

46-
private final Map<String, Object> values = new HashMap<String, Object>();
46+
private final Map<String, Object> values = new LinkedHashMap<String, Object>();
4747

4848

4949
/**

spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/AbstractJdbcCall.java

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
* This class provides the base SPI for {@link SimpleJdbcCall}.
4444
*
4545
* @author Thomas Risberg
46+
* @author Juergen Hoeller
4647
* @since 2.5
4748
*/
4849
public abstract class AbstractJdbcCall {
@@ -63,17 +64,16 @@ public abstract class AbstractJdbcCall {
6364
private final Map<String, RowMapper<?>> declaredRowMappers = new LinkedHashMap<String, RowMapper<?>>();
6465

6566
/**
66-
* Has this operation been compiled? Compilation means at
67-
* least checking that a DataSource and sql have been provided,
68-
* but subclasses may also implement their own custom validation.
67+
* Has this operation been compiled? Compilation means at least checking
68+
* that a DataSource or JdbcTemplate has been provided.
6969
*/
7070
private boolean compiled = false;
7171

7272
/** The generated string used for call statement */
7373
private String callString;
7474

7575
/**
76-
* Object enabling us to create CallableStatementCreators
76+
* A delegate enabling us to create CallableStatementCreators
7777
* efficiently, based on this class's declared parameters.
7878
*/
7979
private CallableStatementCreatorFactory callableStatementFactory;
@@ -92,6 +92,7 @@ protected AbstractJdbcCall(DataSource dataSource) {
9292
* @param jdbcTemplate the JdbcTemplate to use
9393
*/
9494
protected AbstractJdbcCall(JdbcTemplate jdbcTemplate) {
95+
Assert.notNull(jdbcTemplate, "JdbcTemplate must not be null");
9596
this.jdbcTemplate = jdbcTemplate;
9697
}
9798

@@ -161,6 +162,7 @@ public String getSchemaName() {
161162

162163
/**
163164
* Specify whether this call is a function call.
165+
* The default is {@code false}.
164166
*/
165167
public void setFunction(boolean function) {
166168
this.callMetaDataContext.setFunction(function);
@@ -174,7 +176,8 @@ public boolean isFunction() {
174176
}
175177

176178
/**
177-
* Specify whether the call requires a rerurn value.
179+
* Specify whether the call requires a return value.
180+
* The default is {@code false}.
178181
*/
179182
public void setReturnValueRequired(boolean returnValueRequired) {
180183
this.callMetaDataContext.setReturnValueRequired(returnValueRequired);
@@ -188,7 +191,8 @@ public boolean isReturnValueRequired() {
188191
}
189192

190193
/**
191-
* Specify whether the parameter metadata for the call should be used. The default is true.
194+
* Specify whether the parameter metadata for the call should be used.
195+
* The default is {@code true}.
192196
*/
193197
public void setAccessCallParameterMetaData(boolean accessCallParameterMetaData) {
194198
this.callMetaDataContext.setAccessCallParameterMetaData(accessCallParameterMetaData);
@@ -211,10 +215,10 @@ protected CallableStatementCreatorFactory getCallableStatementFactory() {
211215

212216
/**
213217
* Add a declared parameter to the list of parameters for the call.
214-
* Only parameters declared as {@code SqlParameter} and {@code SqlInOutParameter}
215-
* will be used to provide input values. This is different from the {@code StoredProcedure} class
216-
* which for backwards compatibility reasons allows input values to be provided for parameters declared
217-
* as {@code SqlOutParameter}.
218+
* <p>Only parameters declared as {@code SqlParameter} and {@code SqlInOutParameter} will
219+
* be used to provide input values. This is different from the {@code StoredProcedure}
220+
* class which - for backwards compatibility reasons - allows input values to be provided
221+
* for parameters declared as {@code SqlOutParameter}.
218222
* @param parameter the {@link SqlParameter} to add
219223
*/
220224
public void addDeclaredParameter(SqlParameter parameter) {
@@ -247,9 +251,9 @@ public void addDeclaredRowMapper(String parameterName, RowMapper<?> rowMapper) {
247251
//-------------------------------------------------------------------------
248252

249253
/**
250-
* Compile this JdbcCall using provided parameters and meta data plus other settings. This
251-
* finalizes the configuration for this object and subsequent attempts to compile are ignored.
252-
* This will be implicitly called the first time an un-compiled call is executed.
254+
* Compile this JdbcCall using provided parameters and meta data plus other settings.
255+
* <p>This finalizes the configuration for this object and subsequent attempts to compile are
256+
* ignored. This will be implicitly called the first time an un-compiled call is executed.
253257
* @throws org.springframework.dao.InvalidDataAccessApiUsageException if the object hasn't
254258
* been correctly initialized, for example if no DataSource has been provided
255259
*/
@@ -267,19 +271,21 @@ public synchronized final void compile() throws InvalidDataAccessApiUsageExcepti
267271
compileInternal();
268272
this.compiled = true;
269273
if (logger.isDebugEnabled()) {
270-
logger.debug("SqlCall for " + (isFunction() ? "function" : "procedure") + " [" + getProcedureName() + "] compiled");
274+
logger.debug("SqlCall for " + (isFunction() ? "function" : "procedure") +
275+
" [" + getProcedureName() + "] compiled");
271276
}
272277
}
273278
}
274279

275280
/**
276-
* Method to perform the actual compilation. Subclasses can override this template method to perform
277-
* their own compilation. Invoked after this base class's compilation is complete.
281+
* Delegate method to perform the actual compilation.
282+
* <p>Subclasses can override this template method to perform their own compilation.
283+
* Invoked after this base class's compilation is complete.
278284
*/
279285
protected void compileInternal() {
280286
this.callMetaDataContext.initializeMetaData(getJdbcTemplate().getDataSource());
281287

282-
// iterate over the declared RowMappers and register the corresponding SqlParameter
288+
// Iterate over the declared RowMappers and register the corresponding SqlParameter
283289
for (Map.Entry<String, RowMapper<?>> entry : this.declaredRowMappers.entrySet()) {
284290
SqlParameter resultSetParameter =
285291
this.callMetaDataContext.createReturnResultSetParameter(entry.getKey(), entry.getValue());
@@ -332,7 +338,7 @@ protected void checkCompiled() {
332338
//-------------------------------------------------------------------------
333339

334340
/**
335-
* Method that provides execution of the call using the passed in {@link SqlParameterSource}
341+
* Delegate method that executes the call using the passed-in {@link SqlParameterSource}.
336342
* @param parameterSource parameter names and values to be used in call
337343
* @return Map of out parameters
338344
*/
@@ -343,18 +349,19 @@ protected Map<String, Object> doExecute(SqlParameterSource parameterSource) {
343349
}
344350

345351
/**
346-
* Method that provides execution of the call using the passed in array of parameters
347-
* @param args array of parameter values; order must match the order declared for the stored procedure
352+
* Delegate method that executes the call using the passed-in array of parameters.
353+
* @param args array of parameter values. The order of values must match the order
354+
* declared for the stored procedure.
348355
* @return Map of out parameters
349356
*/
350-
protected Map<String, Object> doExecute(Object[] args) {
357+
protected Map<String, Object> doExecute(Object... args) {
351358
checkCompiled();
352359
Map<String, ?> params = matchInParameterValuesWithCallParameters(args);
353360
return executeCallInternal(params);
354361
}
355362

356363
/**
357-
* Method that provides execution of the call using the passed in Map of parameters
364+
* Delegate method that executes the call using the passed-in Map of parameters.
358365
* @param args Map of parameter name and values
359366
* @return Map of out parameters
360367
*/
@@ -365,7 +372,7 @@ protected Map<String, Object> doExecute(Map<String, ?> args) {
365372
}
366373

367374
/**
368-
* Method to perform the actual call processing
375+
* Delegate method to perform the actual call processing.
369376
*/
370377
private Map<String, Object> executeCallInternal(Map<String, ?> args) {
371378
CallableStatementCreator csc = getCallableStatementFactory().newCallableStatementCreator(args);
@@ -391,8 +398,8 @@ protected String getScalarOutParameterName() {
391398
}
392399

393400
/**
394-
* Get a List of all the call parameters to be used for call. This includes any parameters added
395-
* based on meta data processing.
401+
* Get a List of all the call parameters to be used for call.
402+
* This includes any parameters added based on meta data processing.
396403
*/
397404
protected List<SqlParameter> getCallParameters() {
398405
return this.callMetaDataContext.getCallParameters();

0 commit comments

Comments
 (0)