Browse Source

CallMetaDataContext handles 'procedureColumnResult' as return parameter

Issue: SPR-16611
pull/1744/merge
Juergen Hoeller 8 years ago
parent
commit
b7c423813d
  1. 50
      spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java
  2. 18
      spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallParameterMetaData.java

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

@ -44,7 +44,8 @@ import org.springframework.util.Assert;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
* Class to manage context metadata used for the configuration and execution of the call. * Class to manage context meta-data used for the configuration
* and execution of a stored procedure call.
* *
* @author Thomas Risberg * @author Thomas Risberg
* @author Juergen Hoeller * @author Juergen Hoeller
@ -87,13 +88,13 @@ public class CallMetaDataContext {
// Indicates whether this procedure's return value should be included // Indicates whether this procedure's return value should be included
private boolean returnValueRequired = false; private boolean returnValueRequired = false;
// Should we access call parameter meta data info or not // Should we access call parameter meta-data info or not
private boolean accessCallParameterMetaData = true; private boolean accessCallParameterMetaData = true;
// Should we bind parameter by name // Should we bind parameter by name
private boolean namedBinding; private boolean namedBinding;
// The provider of call meta data // The provider of call meta-data
@Nullable @Nullable
private CallMetaDataProvider metaDataProvider; private CallMetaDataProvider metaDataProvider;
@ -214,14 +215,14 @@ public class CallMetaDataContext {
} }
/** /**
* Specify whether call parameter metadata should be accessed. * Specify whether call parameter meta-data should be accessed.
*/ */
public void setAccessCallParameterMetaData(boolean accessCallParameterMetaData) { public void setAccessCallParameterMetaData(boolean accessCallParameterMetaData) {
this.accessCallParameterMetaData = accessCallParameterMetaData; this.accessCallParameterMetaData = accessCallParameterMetaData;
} }
/** /**
* Check whether call parameter metadata should be accessed. * Check whether call parameter meta-data should be accessed.
*/ */
public boolean isAccessCallParameterMetaData() { public boolean isAccessCallParameterMetaData() {
return this.accessCallParameterMetaData; return this.accessCallParameterMetaData;
@ -245,8 +246,8 @@ public class CallMetaDataContext {
/** /**
* Initialize this class with metadata from the database. * Initialize this class with meta-data from the database.
* @param dataSource the DataSource used to retrieve metadata * @param dataSource the DataSource used to retrieve meta-data
*/ */
public void initializeMetaData(DataSource dataSource) { public void initializeMetaData(DataSource dataSource) {
this.metaDataProvider = CallMetaDataProviderFactory.createMetaDataProvider(dataSource, this); this.metaDataProvider = CallMetaDataProviderFactory.createMetaDataProvider(dataSource, this);
@ -305,8 +306,8 @@ public class CallMetaDataContext {
} }
/** /**
* Process the list of parameters provided, and if procedure column metadata is used, * Process the list of parameters provided, and if procedure column meta-data is used,
* the parameters will be matched against the metadata information and any missing * the parameters will be matched against the meta-data information and any missing
* ones will be automatically included. * ones will be automatically included.
* @param parameters the list of parameters to use as a base * @param parameters the list of parameters to use as a base
*/ */
@ -315,7 +316,7 @@ public class CallMetaDataContext {
} }
/** /**
* Reconcile the provided parameters with available metadata and add new ones where appropriate. * Reconcile the provided parameters with available meta-data and add new ones where appropriate.
*/ */
protected List<SqlParameter> reconcileParameters(List<SqlParameter> parameters) { protected List<SqlParameter> reconcileParameters(List<SqlParameter> parameters) {
CallMetaDataProvider provider = obtainMetaDataProvider(); CallMetaDataProvider provider = obtainMetaDataProvider();
@ -326,9 +327,9 @@ public class CallMetaDataContext {
List<String> outParamNames = new ArrayList<>(); List<String> outParamNames = new ArrayList<>();
List<String> metaDataParamNames = new ArrayList<>(); List<String> metaDataParamNames = new ArrayList<>();
// Get the names of the meta data parameters // Get the names of the meta-data parameters
for (CallParameterMetaData meta : provider.getCallParameterMetaData()) { for (CallParameterMetaData meta : provider.getCallParameterMetaData()) {
if (meta.getParameterType() != DatabaseMetaData.procedureColumnReturn) { if (!meta.isReturnParameter()) {
metaDataParamNames.add(lowerCase(meta.getParameterName())); metaDataParamNames.add(lowerCase(meta.getParameterName()));
} }
} }
@ -380,10 +381,9 @@ public class CallMetaDataContext {
paramNameToCheck = lowerCase(provider.parameterNameToUse(paramName)); paramNameToCheck = lowerCase(provider.parameterNameToUse(paramName));
} }
String paramNameToUse = provider.parameterNameToUse(paramName); String paramNameToUse = provider.parameterNameToUse(paramName);
if (declaredParams.containsKey(paramNameToCheck) || if (declaredParams.containsKey(paramNameToCheck) || (meta.isReturnParameter() && returnDeclared)) {
(meta.getParameterType() == DatabaseMetaData.procedureColumnReturn && returnDeclared)) {
SqlParameter param; SqlParameter param;
if (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn) { if (meta.isReturnParameter()) {
param = declaredParams.get(getFunctionReturnName()); param = declaredParams.get(getFunctionReturnName());
if (param == null && !getOutParameterNames().isEmpty()) { if (param == null && !getOutParameterNames().isEmpty()) {
param = declaredParams.get(getOutParameterNames().get(0).toLowerCase()); param = declaredParams.get(getOutParameterNames().get(0).toLowerCase());
@ -409,11 +409,12 @@ public class CallMetaDataContext {
} }
} }
else { else {
if (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn) { if (meta.isReturnParameter()) {
// DatabaseMetaData.procedureColumnReturn or possibly procedureColumnResult
if (!isFunction() && !isReturnValueRequired() && paramName != null && if (!isFunction() && !isReturnValueRequired() && paramName != null &&
provider.byPassReturnParameter(paramName)) { provider.byPassReturnParameter(paramName)) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Bypassing metadata return parameter for '" + paramName + "'"); logger.debug("Bypassing meta-data return parameter for '" + paramName + "'");
} }
} }
else { else {
@ -425,7 +426,7 @@ public class CallMetaDataContext {
outParamNames.add(returnNameToUse); outParamNames.add(returnNameToUse);
} }
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Added metadata return parameter for '" + returnNameToUse + "'"); logger.debug("Added meta-data return parameter for '" + returnNameToUse + "'");
} }
} }
} }
@ -437,22 +438,23 @@ public class CallMetaDataContext {
workParams.add(provider.createDefaultOutParameter(paramNameToUse, meta)); workParams.add(provider.createDefaultOutParameter(paramNameToUse, meta));
outParamNames.add(paramNameToUse); outParamNames.add(paramNameToUse);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Added metadata out parameter for '" + paramNameToUse + "'"); logger.debug("Added meta-data out parameter for '" + paramNameToUse + "'");
} }
} }
else if (meta.getParameterType() == DatabaseMetaData.procedureColumnInOut) { else if (meta.getParameterType() == DatabaseMetaData.procedureColumnInOut) {
workParams.add(provider.createDefaultInOutParameter(paramNameToUse, meta)); workParams.add(provider.createDefaultInOutParameter(paramNameToUse, meta));
outParamNames.add(paramNameToUse); outParamNames.add(paramNameToUse);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Added metadata in out parameter for '" + paramNameToUse + "'"); logger.debug("Added meta-data in-out parameter for '" + paramNameToUse + "'");
} }
} }
else { else {
// DatabaseMetaData.procedureColumnIn or possibly procedureColumnUnknown
if (this.limitedInParameterNames.isEmpty() || if (this.limitedInParameterNames.isEmpty() ||
limitedInParamNamesMap.containsKey(lowerCase(paramNameToUse))) { limitedInParamNamesMap.containsKey(lowerCase(paramNameToUse))) {
workParams.add(provider.createDefaultInParameter(paramNameToUse, meta)); workParams.add(provider.createDefaultInParameter(paramNameToUse, meta));
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Added metadata in parameter for '" + paramNameToUse + "'"); logger.debug("Added meta-data in parameter for '" + paramNameToUse + "'");
} }
} }
else { else {
@ -476,7 +478,7 @@ public class CallMetaDataContext {
*/ */
public Map<String, Object> matchInParameterValuesWithCallParameters(SqlParameterSource parameterSource) { public Map<String, Object> matchInParameterValuesWithCallParameters(SqlParameterSource parameterSource) {
// For parameter source lookups we need to provide case-insensitive lookup support // For parameter source lookups we need to provide case-insensitive lookup support
// since the database metadata is not necessarily providing case sensitive parameter names. // since the database meta-data is not necessarily providing case sensitive parameter names.
Map<String, String> caseInsensitiveParameterNames = Map<String, String> caseInsensitiveParameterNames =
SqlParameterSourceUtils.extractCaseInsensitiveParameterNames(parameterSource); SqlParameterSourceUtils.extractCaseInsensitiveParameterNames(parameterSource);
@ -612,7 +614,7 @@ public class CallMetaDataContext {
} }
/** /**
* Build the call string based on configuration and metadata information. * Build the call string based on configuration and meta-data information.
* @return the call string to be used * @return the call string to be used
*/ */
public String createCallString() { public String createCallString() {
@ -651,7 +653,7 @@ public class CallMetaDataContext {
} }
for (SqlParameter parameter : this.callParameters) { for (SqlParameter parameter : this.callParameters) {
if (!(parameter.isResultsParameter())) { if (!parameter.isResultsParameter()) {
if (parameterCount > 0) { if (parameterCount > 0) {
callString.append(", "); callString.append(", ");
} }

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

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2017 the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,12 +16,15 @@
package org.springframework.jdbc.core.metadata; package org.springframework.jdbc.core.metadata;
import java.sql.DatabaseMetaData;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
/** /**
* Holder of metadata for a specific parameter that is used for call processing. * Holder of meta-data for a specific parameter that is used for call processing.
* *
* @author Thomas Risberg * @author Thomas Risberg
* @author Juergen Hoeller
* @since 2.5 * @since 2.5
* @see GenericCallMetaDataProvider * @see GenericCallMetaDataProvider
*/ */
@ -69,6 +72,17 @@ public class CallParameterMetaData {
return this.parameterType; return this.parameterType;
} }
/**
* Determine whether the declared parameter qualifies as a 'return' parameter
* for our purposes: type {@link DatabaseMetaData#procedureColumnReturn} or
* {@link DatabaseMetaData#procedureColumnResult}.
* @since 4.3.15
*/
public boolean isReturnParameter() {
return (this.parameterType == DatabaseMetaData.procedureColumnReturn ||
this.parameterType == DatabaseMetaData.procedureColumnResult);
}
/** /**
* Get the parameter SQL type. * Get the parameter SQL type.
*/ */

Loading…
Cancel
Save