From b7c423813db7921b726b493b97357eb01d527dd1 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 19 Mar 2018 12:04:15 +0100 Subject: [PATCH] CallMetaDataContext handles 'procedureColumnResult' as return parameter Issue: SPR-16611 --- .../core/metadata/CallMetaDataContext.java | 50 ++++++++++--------- .../core/metadata/CallParameterMetaData.java | 18 ++++++- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java index 978aea2f06..bcf39c9926 100755 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java +++ b/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; /** - * 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 Juergen Hoeller @@ -87,13 +88,13 @@ public class CallMetaDataContext { // Indicates whether this procedure's return value should be included 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; // Should we bind parameter by name private boolean namedBinding; - // The provider of call meta data + // The provider of call meta-data @Nullable 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) { this.accessCallParameterMetaData = accessCallParameterMetaData; } /** - * Check whether call parameter metadata should be accessed. + * Check whether call parameter meta-data should be accessed. */ public boolean isAccessCallParameterMetaData() { return this.accessCallParameterMetaData; @@ -245,8 +246,8 @@ public class CallMetaDataContext { /** - * Initialize this class with metadata from the database. - * @param dataSource the DataSource used to retrieve metadata + * Initialize this class with meta-data from the database. + * @param dataSource the DataSource used to retrieve meta-data */ public void initializeMetaData(DataSource dataSource) { 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, - * the parameters will be matched against the metadata information and any missing + * Process the list of parameters provided, and if procedure column meta-data is used, + * the parameters will be matched against the meta-data information and any missing * ones will be automatically included. * @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 reconcileParameters(List parameters) { CallMetaDataProvider provider = obtainMetaDataProvider(); @@ -326,9 +327,9 @@ public class CallMetaDataContext { List outParamNames = new ArrayList<>(); List metaDataParamNames = new ArrayList<>(); - // Get the names of the meta data parameters + // Get the names of the meta-data parameters for (CallParameterMetaData meta : provider.getCallParameterMetaData()) { - if (meta.getParameterType() != DatabaseMetaData.procedureColumnReturn) { + if (!meta.isReturnParameter()) { metaDataParamNames.add(lowerCase(meta.getParameterName())); } } @@ -380,10 +381,9 @@ public class CallMetaDataContext { paramNameToCheck = lowerCase(provider.parameterNameToUse(paramName)); } String paramNameToUse = provider.parameterNameToUse(paramName); - if (declaredParams.containsKey(paramNameToCheck) || - (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn && returnDeclared)) { + if (declaredParams.containsKey(paramNameToCheck) || (meta.isReturnParameter() && returnDeclared)) { SqlParameter param; - if (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn) { + if (meta.isReturnParameter()) { param = declaredParams.get(getFunctionReturnName()); if (param == null && !getOutParameterNames().isEmpty()) { param = declaredParams.get(getOutParameterNames().get(0).toLowerCase()); @@ -409,11 +409,12 @@ public class CallMetaDataContext { } } else { - if (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn) { + if (meta.isReturnParameter()) { + // DatabaseMetaData.procedureColumnReturn or possibly procedureColumnResult if (!isFunction() && !isReturnValueRequired() && paramName != null && provider.byPassReturnParameter(paramName)) { if (logger.isDebugEnabled()) { - logger.debug("Bypassing metadata return parameter for '" + paramName + "'"); + logger.debug("Bypassing meta-data return parameter for '" + paramName + "'"); } } else { @@ -425,7 +426,7 @@ public class CallMetaDataContext { outParamNames.add(returnNameToUse); } 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)); outParamNames.add(paramNameToUse); 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) { workParams.add(provider.createDefaultInOutParameter(paramNameToUse, meta)); outParamNames.add(paramNameToUse); if (logger.isDebugEnabled()) { - logger.debug("Added metadata in out parameter for '" + paramNameToUse + "'"); + logger.debug("Added meta-data in-out parameter for '" + paramNameToUse + "'"); } } else { + // DatabaseMetaData.procedureColumnIn or possibly procedureColumnUnknown if (this.limitedInParameterNames.isEmpty() || limitedInParamNamesMap.containsKey(lowerCase(paramNameToUse))) { workParams.add(provider.createDefaultInParameter(paramNameToUse, meta)); if (logger.isDebugEnabled()) { - logger.debug("Added metadata in parameter for '" + paramNameToUse + "'"); + logger.debug("Added meta-data in parameter for '" + paramNameToUse + "'"); } } else { @@ -476,7 +478,7 @@ public class CallMetaDataContext { */ public Map matchInParameterValuesWithCallParameters(SqlParameterSource parameterSource) { // 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 caseInsensitiveParameterNames = 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 */ public String createCallString() { @@ -651,7 +653,7 @@ public class CallMetaDataContext { } for (SqlParameter parameter : this.callParameters) { - if (!(parameter.isResultsParameter())) { + if (!parameter.isResultsParameter()) { if (parameterCount > 0) { callString.append(", "); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallParameterMetaData.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallParameterMetaData.java index 764fc79213..9d2a09f5f2 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallParameterMetaData.java +++ b/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"); * you may not use this file except in compliance with the License. @@ -16,12 +16,15 @@ package org.springframework.jdbc.core.metadata; +import java.sql.DatabaseMetaData; + 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 Juergen Hoeller * @since 2.5 * @see GenericCallMetaDataProvider */ @@ -69,6 +72,17 @@ public class CallParameterMetaData { 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. */ -- GitLab