/** * Build the call string based on configuration and metadata information. * * @return the call string to be used */ public String createCallString() { String callString; int parameterCount = 0; String catalogNameToUse; String schemaNameToUse; // For Oracle where catalogs are not supported we need to reverse the schema name // and the catalog name since the cataog is used for the package name if (this.metaDataProvider.isSupportsSchemasInProcedureCalls() && !this.metaDataProvider.isSupportsCatalogsInProcedureCalls()) { schemaNameToUse = this.metaDataProvider.catalogNameToUse(getCatalogName()); catalogNameToUse = this.metaDataProvider.schemaNameToUse(getSchemaName()); } else { catalogNameToUse = this.metaDataProvider.catalogNameToUse(getCatalogName()); schemaNameToUse = this.metaDataProvider.schemaNameToUse(getSchemaName()); } String procedureNameToUse = this.metaDataProvider.procedureNameToUse(getProcedureName()); if (isFunction() || isReturnValueRequired()) { callString = "{? = call " + (StringUtils.hasLength(catalogNameToUse) ? catalogNameToUse + "." : "") + (StringUtils.hasLength(schemaNameToUse) ? schemaNameToUse + "." : "") + procedureNameToUse + "("; parameterCount = -1; } else { callString = "{call " + (StringUtils.hasLength(catalogNameToUse) ? catalogNameToUse + "." : "") + (StringUtils.hasLength(schemaNameToUse) ? schemaNameToUse + "." : "") + procedureNameToUse + "("; } for (SqlParameter parameter : this.callParameters) { if (!(parameter.isResultsParameter())) { if (parameterCount > 0) { callString += ", "; } if (parameterCount >= 0) { callString += createParameterBinding(parameter); } parameterCount++; } } callString += ")}"; return callString; }
/** * Overridden method to configure the CallableStatementCreatorFactory based on our declared * parameters. * * @see RdbmsOperation#compileInternal() */ @Override protected final void compileInternal() { if (isSqlReadyForUse()) { this.callString = getSql(); } else { List<SqlParameter> parameters = getDeclaredParameters(); int parameterCount = 0; if (isFunction()) { this.callString = "{? = call " + getSql() + "("; parameterCount = -1; } else { this.callString = "{call " + getSql() + "("; } for (SqlParameter parameter : parameters) { if (!(parameter.isResultsParameter())) { if (parameterCount > 0) { this.callString += ", "; } if (parameterCount >= 0) { this.callString += "?"; } parameterCount++; } } this.callString += ")}"; } if (logger.isDebugEnabled()) { logger.debug("Compiled stored procedure. Call string is [" + getCallString() + "]"); } this.callableStatementFactory = new CallableStatementCreatorFactory(getCallString(), getDeclaredParameters()); this.callableStatementFactory.setResultSetType(getResultSetType()); this.callableStatementFactory.setUpdatableResults(isUpdatableResults()); this.callableStatementFactory.setNativeJdbcExtractor( getJdbcTemplate().getNativeJdbcExtractor()); onCompileInternal(); }
/** * Reconcile the provided parameters with available metadata and add new ones where appropriate. */ protected List<SqlParameter> reconcileParameters(List<SqlParameter> parameters) { final List<SqlParameter> declaredReturnParams = new ArrayList<SqlParameter>(); final Map<String, SqlParameter> declaredParams = new LinkedHashMap<String, SqlParameter>(); boolean returnDeclared = false; List<String> outParamNames = new ArrayList<String>(); List<String> metaDataParamNames = new ArrayList<String>(); // Get the names of the meta data parameters for (CallParameterMetaData meta : this.metaDataProvider.getCallParameterMetaData()) { if (meta.getParameterType() != DatabaseMetaData.procedureColumnReturn) { metaDataParamNames.add(meta.getParameterName().toLowerCase()); } } // Separate implicit return parameters from explicit parameters... for (SqlParameter param : parameters) { if (param.isResultsParameter()) { declaredReturnParams.add(param); } else { String paramName = param.getName(); if (paramName == null) { throw new IllegalArgumentException( "Anonymous parameters not supported for calls - " + "please specify a name for the parameter of SQL type " + param.getSqlType()); } String paramNameToMatch = this.metaDataProvider.parameterNameToUse(paramName).toLowerCase(); declaredParams.put(paramNameToMatch, param); if (param instanceof SqlOutParameter) { outParamNames.add(paramName); if (isFunction() && !metaDataParamNames.contains(paramNameToMatch)) { if (!returnDeclared) { if (logger.isDebugEnabled()) { logger.debug( "Using declared out parameter '" + paramName + "' for function return value"); } setFunctionReturnName(paramName); returnDeclared = true; } } } } } setOutParameterNames(outParamNames); List<SqlParameter> workParams = new ArrayList<SqlParameter>(); workParams.addAll(declaredReturnParams); if (!this.metaDataProvider.isProcedureColumnMetaDataUsed()) { workParams.addAll(declaredParams.values()); return workParams; } Map<String, String> limitedInParamNamesMap = new HashMap<String, String>(this.limitedInParameterNames.size()); for (String limitedParamName : this.limitedInParameterNames) { limitedInParamNamesMap.put( this.metaDataProvider.parameterNameToUse(limitedParamName).toLowerCase(), limitedParamName); } for (CallParameterMetaData meta : this.metaDataProvider.getCallParameterMetaData()) { String paramNameToCheck = null; if (meta.getParameterName() != null) { paramNameToCheck = this.metaDataProvider.parameterNameToUse(meta.getParameterName()).toLowerCase(); } String paramNameToUse = this.metaDataProvider.parameterNameToUse(meta.getParameterName()); if (declaredParams.containsKey(paramNameToCheck) || (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn && returnDeclared)) { SqlParameter param; if (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn) { param = declaredParams.get(getFunctionReturnName()); if (param == null && getOutParameterNames().size() > 0) { param = declaredParams.get(getOutParameterNames().get(0).toLowerCase()); } if (param == null) { throw new InvalidDataAccessApiUsageException( "Unable to locate declared parameter for function return value - " + " add a SqlOutParameter with name '" + getFunctionReturnName() + "'"); } else { setFunctionReturnName(param.getName()); } } else { param = declaredParams.get(paramNameToCheck); } if (param != null) { workParams.add(param); if (logger.isDebugEnabled()) { logger.debug( "Using declared parameter for '" + (paramNameToUse != null ? paramNameToUse : getFunctionReturnName()) + "'"); } } } else { if (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn) { if (!isFunction() && !isReturnValueRequired() && this.metaDataProvider.byPassReturnParameter(meta.getParameterName())) { if (logger.isDebugEnabled()) { logger.debug( "Bypassing metadata return parameter for '" + meta.getParameterName() + "'"); } } else { String returnNameToUse = (StringUtils.hasLength(meta.getParameterName()) ? paramNameToUse : getFunctionReturnName()); workParams.add(this.metaDataProvider.createDefaultOutParameter(returnNameToUse, meta)); if (isFunction()) { setFunctionReturnName(returnNameToUse); outParamNames.add(returnNameToUse); } if (logger.isDebugEnabled()) { logger.debug("Added metadata return parameter for '" + returnNameToUse + "'"); } } } else { if (meta.getParameterType() == DatabaseMetaData.procedureColumnOut) { workParams.add(this.metaDataProvider.createDefaultOutParameter(paramNameToUse, meta)); outParamNames.add(paramNameToUse); if (logger.isDebugEnabled()) { logger.debug("Added metadata out parameter for '" + paramNameToUse + "'"); } } else if (meta.getParameterType() == DatabaseMetaData.procedureColumnInOut) { workParams.add(this.metaDataProvider.createDefaultInOutParameter(paramNameToUse, meta)); outParamNames.add(paramNameToUse); if (logger.isDebugEnabled()) { logger.debug("Added metadata in out parameter for '" + paramNameToUse + "'"); } } else { if (this.limitedInParameterNames.isEmpty() || limitedInParamNamesMap.containsKey(paramNameToUse.toLowerCase())) { workParams.add(this.metaDataProvider.createDefaultInParameter(paramNameToUse, meta)); if (logger.isDebugEnabled()) { logger.debug("Added metadata in parameter for '" + paramNameToUse + "'"); } } else { if (logger.isDebugEnabled()) { logger.debug( "Limited set of parameters " + limitedInParamNamesMap.keySet() + " skipped parameter for '" + paramNameToUse + "'"); } } } } } } return workParams; }