CallMetaDataContext handles 'procedureColumnResult' as return parameter
Issue: SPR-16611
This commit is contained in:
@@ -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(", ");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user