Функция вызова SimpleJdbcCall

#java #oracle #spring-jdbc #dto

#java #Oracle #spring-jdbc #dto

Вопрос:

У меня есть функция Oracle с именем GET_RISK_GROUP.

Когда я пытаюсь вызвать эту функцию:

 SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
                .withSchemaName("NEWIB")
                .withCatalogName("PKG_ONLINE_IB_PC_OPERATIONS")
                .withFunctionName("GET_RISK_GROUP");
        SqlParameterSource source = new MapSqlParameterSource().addValue("P_TAX_NUMBER", taxNumber);
        jdbcCall.executeFunction(String.class, source);
  

Я получаю исключение:

 2020-09-11 15:40:25.692 ERROR 1276 --- [nio-8698-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{? = call GET_RISK_GROUP()}]; SQL state [99999]; error code [17041]; Missing IN or OUT parameter at index:: 1; nested exception is java.sql.SQLException: Missing IN or OUT parameter at index:: 1] with root cause
  

Не удалось найти какое-либо решение. Есть идеи? Из-за этой проблемы я изменил свой код на:

 jdbcTemplate.execute(
                con -> {
                    CallableStatement cs = con.prepareCall("{? = call NEWIB.PKG_ONLINE_IB_PC_OPERATIONS.GET_RISK_GROUP(?)}");
                    cs.registerOutParameter(1, Types.NVARCHAR); // or whatever type your function returns.
                    // Set your arguments
                    cs.setString(2, taxNumber);
                    return cs;
                },
                (CallableStatementCallback<String>) cs -> {
                    cs.execute();
                    String result = cs.getString(1);
                    return resu< // Whatever is returned here is returned from the jdbcTemplate.execute method
                }
        );
  

Это работает нормально.

Ответ №1:

Имея опыт в этом, я мог бы только сказать, чтобы просто внести некоторые стандартные изменения, а затем попробовать, потому что тот же код работает так, как вы сказали, работает на моей машине. Точно не помню, но в одном из вопросов SO упоминалось, что драйвер jdbc может иметь значение.

Я добавил withoutProcedureColumnMetaDataAccess это, потому что SimpleJdbcCall мне нравится очень часто запрашивать метаданные сведений о столбце, и чтобы избежать проблем с производительностью в будущем, когда у нас будет больше таких вызовов, желательно добавить это.

Для вызова функции нам также необходимо зарегистрировать (как вы сделали с CallableStatement ) или объявить его в качестве первого параметра, который будет действовать как возвращаемый тип для.

Я надеюсь, что приведенное ниже работает ,

 SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
                .withSchemaName("NEWIB")
                .withCatalogName("PKG_ONLINE_IB_PC_OPERATIONS")
                .withFunctionName("GET_RISK_GROUP")
                .withoutProcedureColumnMetaDataAccess()
                .declareParameters(new SqlOutParameter("return",Types.VARCHAR),
                                   new SqlParameter("p_tax_number", Types.VARCHAR));
        
// add value to the paramaters                         
SqlParameterSource parameterMap = new MapSqlParameterSource().addValue("p_tax_number", taxNumber);
        
// call
String result = jdbcCall.executeFunction(String.class, source);
  

Постскриптум
Если не работает, не могли бы вы опубликовать тело функции в вопросе или выполнить приведенный ниже запрос и вставить результат здесь

 select object_name,argument_name,position,data_type,data_length,in_out 
from   user_arguments
where  OBJECT_NAME ='GET_RISK_GROUP' 
and    Package_name='PKG_ONLINE_IB_PC_OPERATIONS'