【问题标题】:Permanent ORA-06550 error, calling stored function from java application using jdbc永久性 ORA-06550 错误,使用 jdbc 从 java 应用程序调用存储函数
【发布时间】:2020-11-19 01:31:32
【问题描述】:

我正在尝试从我的 java 应用程序中调用几个存储的函数,但是无论我调用什么函数,我都会遇到相同的错误。 例如,给定这个函数:

   function insert_value (input_name varchar2) return number;

我正在尝试使用:

   JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
   SimpleJdbcCall call= new SimpleJdbcCall(jdbcTemplate)
                    .withCatalogName("MY_PACKAGE_NAME")
                    .withFunctionName("insert_value")
                    .withoutProcedureColumnMetaDataAccess()
                    .declareParameters(
                            new SqlParameter("input_name", Types.VARCHAR));
   SqlParameterSource parameterMap = new MapSqlParameterSource()
                 .addValue("input_name", "John Doe");
   int idNumber = call.executeFunction(Integer.class,parameterMap);

我总是遇到同样的错误:

    java.sql.SQLException: ORA-06550: line 1, column 7:
    PLS-00306: wrong number or types of arguments in call to 'INSERT_VALUE'
    ORA-06550: line 1, column 7:
    PL/SQL: Statement ignored

您可以看到参数的名称是正确的,我已经检查了我的 jdbc 驱动程序是否支持命名参数,但我不知道如何在 SimpleJdbcCall 上传递索引而不是参数名称。

有什么建议吗?请记住,我有几个更复杂的函数,我以相同的方式调用它们返回相同的错误。

【问题讨论】:

  • 尝试改用 "call.executeFunction(Integer.class" call.executeFunction(BigDecimal.class
  • 没有任何改变...这也发生在返回 VARCHAR2 的函数中
  • 你试过大写参数名吗?即 INPUT_NAME?
  • 是的,我有。用于参数和函数名
  • 你可以试试 SqlParameterSource parameterMap = new MapSqlParameterSource().addValue("input_name", "John Doe", Types.VARCHAR);

标签: java oracle jdbc plsql simplejdbccall


【解决方案1】:

首先,通过检查元数据表,确保数据库上的对象规范与 Java 应用程序中定义的内容相匹配。 执行查询(如果您没有权限最好从 DBA 负责人那里获取)

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

对象的示例输出,

对于Function,你需要返回参数,它应该是第一个参数。修改代码添加out参数如下。

JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
   SimpleJdbcCall call= new SimpleJdbcCall(jdbcTemplate)
                    .withCatalogName("MY_PACKAGE_NAME")
                    .withFunctionName("insert_value")
                    .withoutProcedureColumnMetaDataAccess()
                    .declareParameters(new SqlOutParameter("return",Types.INTEGER),
                            new SqlParameter("input_name", Types.VARCHAR));
   SqlParameterSource parameterMap = new MapSqlParameterSource()
                 .addValue("input_name", "John Doe");
   int idNumber = call.executeFunction(Integer.class,parameterMap);

但是在处理存储过程时就略有不同,

SimpleJdbcCall jdbcCall = new SimpleJdbcCall(springTemplate) 
.withCatalogName("PACKAGE_NAME").withProcedureName("PROCEDURE_NAME")
.withReturnValue().withoutProcedureColumnMetaDataAccess()
.declareParameters(new SqlParameter("INPUT_PARAMETER", Types.VARCHAR),
new SqlOutParameter("OUTPUT_PARAMETER_NAME", Types.VARCHAR));

如果您有重写的函数/过程,则使用useInParameterNames 指定要包含给给定签名的 IN 参数名称列表。

【讨论】:

    【解决方案2】:

    试试下面,(可能还有其他方法)

    如果我看到失败消息,则 input_name 未绑定到实际调用。

    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
            SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate).withCatalogName("MY_PACKAGE_NAME")
                    .withFunctionName("insert_value");
    
            SqlParameterSource parameterMap = new MapSqlParameterSource().addValue("input_name", "John Doe",
                    Types.VARCHAR);
    
            BigDecimal idNumber = call.executeFunction(BigDecimal.class, parameterMap);
    

    使用您的方法,我们必须指定返回参数,因为在函数的情况下,第一个参数被认为是返回值,因此在这种情况下,第一个参数在实际调用期间总是被省略。

    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
            SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate).withCatalogName("MY_PACKAGE_NAME")
                    .withFunctionName("insert_value").withoutProcedureColumnMetaDataAccess().declareParameters(
                            new SqlOutParameter("return", Types.INTEGER), new SqlParameter("input_name", Types.VARCHAR));
    
            SqlParameterSource parameterMap = new MapSqlParameterSource().addValue((String) "input_name", "John Doe",
                    Types.VARCHAR);
    
            Integer idNumber = call.executeFunction(Integer.class, parameterMap);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-12
      • 2013-12-02
      • 2012-08-25
      • 2011-12-26
      • 2012-01-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多