Search in sources :

Example 6 with SqlParameter

use of org.springframework.jdbc.core.SqlParameter in project spring-framework by spring-projects.

the class CallMetaDataContext method matchInParameterValuesWithCallParameters.

/**
	 * Match input parameter values with the parameters declared to be used in the call.
	 * @param parameterSource the input values
	 * @return a Map containing the matched parameter names with the value taken from the input
	 */
public Map<String, Object> 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.
    Map<String, String> caseInsensitiveParameterNames = SqlParameterSourceUtils.extractCaseInsensitiveParameterNames(parameterSource);
    Map<String, String> callParameterNames = new HashMap<>(this.callParameters.size());
    Map<String, Object> matchedParameters = new HashMap<>(this.callParameters.size());
    for (SqlParameter parameter : this.callParameters) {
        if (parameter.isInputValueProvided()) {
            String parameterName = parameter.getName();
            String parameterNameToMatch = this.metaDataProvider.parameterNameToUse(parameterName);
            if (parameterNameToMatch != null) {
                callParameterNames.put(parameterNameToMatch.toLowerCase(), parameterName);
            }
            if (parameterName != null) {
                if (parameterSource.hasValue(parameterName)) {
                    matchedParameters.put(parameterName, SqlParameterSourceUtils.getTypedValue(parameterSource, parameterName));
                } else {
                    String lowerCaseName = parameterName.toLowerCase();
                    if (parameterSource.hasValue(lowerCaseName)) {
                        matchedParameters.put(parameterName, SqlParameterSourceUtils.getTypedValue(parameterSource, lowerCaseName));
                    } else {
                        String englishLowerCaseName = parameterName.toLowerCase(Locale.ENGLISH);
                        if (parameterSource.hasValue(englishLowerCaseName)) {
                            matchedParameters.put(parameterName, SqlParameterSourceUtils.getTypedValue(parameterSource, englishLowerCaseName));
                        } else {
                            String propertyName = JdbcUtils.convertUnderscoreNameToPropertyName(parameterName);
                            if (parameterSource.hasValue(propertyName)) {
                                matchedParameters.put(parameterName, SqlParameterSourceUtils.getTypedValue(parameterSource, propertyName));
                            } else {
                                if (caseInsensitiveParameterNames.containsKey(lowerCaseName)) {
                                    String sourceName = caseInsensitiveParameterNames.get(lowerCaseName);
                                    matchedParameters.put(parameterName, SqlParameterSourceUtils.getTypedValue(parameterSource, sourceName));
                                } else {
                                    logger.warn("Unable to locate the corresponding parameter value for '" + parameterName + "' within the parameter values provided: " + caseInsensitiveParameterNames.values());
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    if (logger.isDebugEnabled()) {
        logger.debug("Matching " + caseInsensitiveParameterNames.values() + " with " + callParameterNames.values());
        logger.debug("Found match for " + matchedParameters.keySet());
    }
    return matchedParameters;
}
Also used : SqlParameter(org.springframework.jdbc.core.SqlParameter) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap)

Example 7 with SqlParameter

use of org.springframework.jdbc.core.SqlParameter in project spring-framework by spring-projects.

the class CallMetaDataContext method reconcileParameters.

/**
	 * 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<>();
    final Map<String, SqlParameter> declaredParams = new LinkedHashMap<>();
    boolean returnDeclared = false;
    List<String> outParamNames = new ArrayList<>();
    List<String> metaDataParamNames = new ArrayList<>();
    // 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<>();
    workParams.addAll(declaredReturnParams);
    if (!this.metaDataProvider.isProcedureColumnMetaDataUsed()) {
        workParams.addAll(declaredParams.values());
        return workParams;
    }
    Map<String, String> limitedInParamNamesMap = new HashMap<>(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;
}
Also used : SqlParameter(org.springframework.jdbc.core.SqlParameter) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) SqlOutParameter(org.springframework.jdbc.core.SqlOutParameter) LinkedHashMap(java.util.LinkedHashMap) InvalidDataAccessApiUsageException(org.springframework.dao.InvalidDataAccessApiUsageException)

Example 8 with SqlParameter

use of org.springframework.jdbc.core.SqlParameter in project spring-framework by spring-projects.

the class CallMetaDataContext method createCallString.

/**
	 * 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;
    // 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;
}
Also used : SqlParameter(org.springframework.jdbc.core.SqlParameter)

Example 9 with SqlParameter

use of org.springframework.jdbc.core.SqlParameter in project spring-framework by spring-projects.

the class CallMetaDataContextTests method testMatchParameterValuesAndSqlInOutParameters.

@Test
public void testMatchParameterValuesAndSqlInOutParameters() throws Exception {
    final String TABLE = "customers";
    final String USER = "me";
    given(databaseMetaData.getDatabaseProductName()).willReturn("MyDB");
    given(databaseMetaData.getUserName()).willReturn(USER);
    given(databaseMetaData.storesLowerCaseIdentifiers()).willReturn(true);
    List<SqlParameter> parameters = new ArrayList<>();
    parameters.add(new SqlParameter("id", Types.NUMERIC));
    parameters.add(new SqlInOutParameter("name", Types.NUMERIC));
    parameters.add(new SqlOutParameter("customer_no", Types.NUMERIC));
    MapSqlParameterSource parameterSource = new MapSqlParameterSource();
    parameterSource.addValue("id", 1);
    parameterSource.addValue("name", "Sven");
    parameterSource.addValue("customer_no", "12345XYZ");
    context.setProcedureName(TABLE);
    context.initializeMetaData(dataSource);
    context.processParameters(parameters);
    Map<String, Object> inParameters = context.matchInParameterValuesWithCallParameters(parameterSource);
    assertEquals("Wrong number of matched in parameter values", 2, inParameters.size());
    assertTrue("in parameter value missing", inParameters.containsKey("id"));
    assertTrue("in out parameter value missing", inParameters.containsKey("name"));
    assertTrue("out parameter value matched", !inParameters.containsKey("customer_no"));
    List<String> names = context.getOutParameterNames();
    assertEquals("Wrong number of out parameters", 2, names.size());
    List<SqlParameter> callParameters = context.getCallParameters();
    assertEquals("Wrong number of call parameters", 3, callParameters.size());
}
Also used : SqlParameter(org.springframework.jdbc.core.SqlParameter) MapSqlParameterSource(org.springframework.jdbc.core.namedparam.MapSqlParameterSource) ArrayList(java.util.ArrayList) SqlOutParameter(org.springframework.jdbc.core.SqlOutParameter) SqlInOutParameter(org.springframework.jdbc.core.SqlInOutParameter) Test(org.junit.Test)

Example 10 with SqlParameter

use of org.springframework.jdbc.core.SqlParameter in project spring-framework by spring-projects.

the class SqlUpdateTests method doTestNamedParameterUpdate.

private void doTestNamedParameterUpdate(final boolean namedDeclarations) throws SQLException {
    given(preparedStatement.executeUpdate()).willReturn(1);
    given(connection.prepareStatement(UPDATE_INT_INT)).willReturn(preparedStatement);
    class NamedParameterUpdater extends SqlUpdate {

        public NamedParameterUpdater() {
            setSql(UPDATE_NAMED_PARAMETERS);
            setDataSource(dataSource);
            if (namedDeclarations) {
                declareParameter(new SqlParameter("priceId", Types.DECIMAL));
                declareParameter(new SqlParameter("perfId", Types.NUMERIC));
            } else {
                declareParameter(new SqlParameter(Types.NUMERIC));
                declareParameter(new SqlParameter(Types.DECIMAL));
            }
            compile();
        }

        public int run(int performanceId, int type) {
            Map<String, Integer> params = new HashMap<>();
            params.put("perfId", performanceId);
            params.put("priceId", type);
            return updateByNamedParam(params);
        }
    }
    NamedParameterUpdater pc = new NamedParameterUpdater();
    int rowsAffected = pc.run(1, 1);
    assertEquals(1, rowsAffected);
    verify(preparedStatement).setObject(1, 1, Types.NUMERIC);
    verify(preparedStatement).setObject(2, 1, Types.DECIMAL);
}
Also used : SqlParameter(org.springframework.jdbc.core.SqlParameter) HashMap(java.util.HashMap)

Aggregations

SqlParameter (org.springframework.jdbc.core.SqlParameter)66 BatchSqlUpdate (org.springframework.jdbc.object.BatchSqlUpdate)23 Test (org.junit.Test)22 ResultSet (java.sql.ResultSet)15 DataSource (javax.sql.DataSource)15 HashMap (java.util.HashMap)12 Customer (org.springframework.jdbc.Customer)12 SqlOutParameter (org.springframework.jdbc.core.SqlOutParameter)6 LinkedHashMap (java.util.LinkedHashMap)5 ArrayList (java.util.ArrayList)4 InvalidDataAccessApiUsageException (org.springframework.dao.InvalidDataAccessApiUsageException)4 File (com.github.hakko.musiccabinet.domain.model.library.File)3 PreparedStatementCreatorFactory (org.springframework.jdbc.core.PreparedStatementCreatorFactory)3 MapSqlParameterSource (org.springframework.jdbc.core.namedparam.MapSqlParameterSource)3 Track (com.github.hakko.musiccabinet.domain.model.music.Track)2 PreparedStatement (java.sql.PreparedStatement)2 Map (java.util.Map)2 CallableStatementCreatorFactory (org.springframework.jdbc.core.CallableStatementCreatorFactory)2 SqlParameterValue (org.springframework.jdbc.core.SqlParameterValue)2 DriverManagerDataSource (org.springframework.jdbc.datasource.DriverManagerDataSource)2