SimpleJdbcCall всегда пропускает первый параметр в вызовах функций - PullRequest
0 голосов
/ 04 мая 2018

Я пытаюсь использовать класс SimpleJdbcCall для вызова функций в пакете Oracle, но каждый вызов игнорирует первый входной параметр. Мой код выглядит так:

SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate.getJdbcTemplate())
                .withSchemaName("MY_SCHEMA")
                .withCatalogName("MY_PACKAGE")
                .withFunctionName("MY_FUNCTION")
                .withoutProcedureColumnMetaDataAccess()
                .declareParameters(new SqlParameter("FIRST_ARGUMENT", Types.VARCHAR), new SqlParameter("SECOND_ARGUMENT", Types.VARCHAR));
SqlParameterSource params = new MapSqlParameterSource().addValue("FIRST_ARGUMENT", "VALUE1").addValue("SECOND_ARGUMENT", "VALUE2");
Integer result = call.executeFunction(Integer.class, params);

с моей функцией:

FUNCTION MY_FUNCTION(FIRST_ARGUMENTvarchar2, SECOND_ARGUMENTvarchar2) RETURN number;

В трассировке стека отображаются ошибки такого типа:

org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; bad SQL grammar [{? = call MY_SCHEMA.MY_PACKAGE.MY_FUNCTION(?)}];

Параметр был удален. Вызов другой функции только с одним параметром вызывает похожую ошибку:

org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; bad SQL grammar [{? = call MY_SCHEMA.MY_PACKAGE.MY_OTHER_FUNCTION()}];

Я попытался отладить код Spring, spring-boot-starter-jdbc:2.0.1.RELEASE (тоже 2.0.0), и я наткнулся на этот код в классе org.springframework.jdbc.core.metadata.CallMetaDataContext при составлении вызова:

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 += ")}";

Если я понял код, первый параметр будет всегда опущен, я прав? У кого-нибудь был успех в этой ситуации?


M. Deinum прав, и возвращаемый параметр тоже должен быть указан, я ожидал, что Spring автоматически добавит его при работе с функциями. Мой код сейчас:

    SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate.getJdbcTemplate())
                        .withSchemaName("MY_SCHEMA")
                        .withCatalogName("MY_PACKAGE")
                        .withFunctionName("MY_FUNCTION")
                        .withoutProcedureColumnMetaDataAccess()
                        .declareParameters(new SqlOutParameter("return",Types.INTEGER) 
                                            ,new SqlParameter("FIRST_ARGUMENT", Types.VARCHAR) 
                                            ,new SqlParameter("SECOND_ARGUMENT", Types.VARCHAR));
        SqlParameterSource params = new MapSqlParameterSource().addValue("FIRST_ARGUMENT", "VALUE1").addValue("SECOND_ARGUMENT", "VALUE2");
        Integer result = call.executeFunction(Integer.class, params);
...