程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了使用 java SimpleJdbcCall 调用带有 out 参数类型“is table of varchar2”的过程 oracle大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决使用 java SimpleJdbcCall 调用带有 out 参数类型“is table of varchar2”的过程 Oracle?

开发过程中遇到使用 java SimpleJdbcCall 调用带有 out 参数类型“is table of varchar2”的过程 Oracle的问题如何解决?下面主要结合日常开发的经验,给出你关于使用 java SimpleJdbcCall 调用带有 out 参数类型“is table of varchar2”的过程 Oracle的解决方法建议,希望对你解决使用 java SimpleJdbcCall 调用带有 out 参数类型“is table of varchar2”的过程 Oracle有所启发或帮助;

我创建了一个带有 2 个参数的过程 Oracle,其中一个是 out 参数类型 table OF VARCHAR2 。如何在java中调用它并获得结果?

我的测试程序创建如下:

/* creaTing package with specs */
create or replace PACKAGE PACK1 AS
  TYPE name_array IS table OF VARCHAR2(50) INDEX BY BINARY_IntegeR;
  PROCEDURE proc_filter_and_return_array( p_name_in  IN  VARCHAR2,p_name_out_array OUT name_array );
END PACK1;

/* creaTing package body with procedure */
create or replace PACKAGE BODY PACK1
as
    PROCEDURE proc_filter_and_return_array(
                p_name_in   IN       VARCHAR2,p_name_out_array OUT name_array
    )IS
                cursOR c_table1_SELEct is
                         SELEct name FROM table1_test where name like '%' || p_name_in  || '%';
                v_index numbER := 0;
    BEGIN
            FOR x IN c_table1_SELEct
             LOOP     
               p_name_out_array( v_index ) := x.name;
               v_index := v_index + 1;  
             END LOOP; 
    
    END proc_filter_and_return_array; 
END PACK1;

当我在 Oracle 中测试它时,我成功地使用了以下代码:

DECLARE
    p_name_array pack1.name_array;
BEGIN
    pack1.proc_filter_and_return_array(p_name_in => 'name_to_filter',p_name_out_array => p_name_array);
    DBMS_output.put_line(' number from table: ' || p_name_array(1) );
END;

但是在java中我遇到了一些错误,我正在以这种方式调用过程:

    SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplatE)
        .withCatalogname("PACK1") 
        .withProcedurename("PROC_FILTER_AND_RETURN_ARRAY") 
        .declareParameters( new sqlParameter("P_name_IN",Types.VARCHAR) )
        .declareParameters( new sqlOutParameter("P_name_OUT_ARRAY",Types.ARRAY,"PACK1.name_ARRAY" ));
        
    MapsqlParametersource map = new MapsqlParametersource();
    map.addValue("P_name_IN","name_to_filter");

    Map<String,Object> result = simpleJdbcCall.execute(map);

所以我从 java 运行得到了这个:

org.springframework.jdbc.UncategorizedsqlException: CallableStatementCallBACk; uncategorized sqlException for sql [{Call PACK1.PROC_FILTER_AND_RETURN_ARRAY(?,?)}]; 
sql state [99999]; error code [17074]; invalID name pattern: PACK1.name_ARRAY; nested exception is java.sql.sqlException: invalID name pattern: PACK1.name_ARRAY] with root cause
java.sql.sqlException: invalID name pattern: PACK1.name_ARRAY
        at Oracle.jdbc.Oracore.OracleTypeADT.initMetadata11_2(OracleTypeADT.java:764)
        at Oracle.jdbc.Oracore.OracleTypeADT.initMetadata(OracleTypeADT.java:479)
        at Oracle.jdbc.Oracore.OracleTypeADT.init(OracleTypeADT.java:443)
        at Oracle.sql.ArrayDescriptor.initPickler(ArrayDescriptor.java:1499)
        at Oracle.sql.ArrayDescriptor.<init>(ArrayDescriptor.java:274)
        at Oracle.sql.ArrayDescriptor.createDescriptor(ArrayDescriptor.java:127)
        at Oracle.sql.ArrayDescriptor.createDescriptor(ArrayDescriptor.java:79)
        at Oracle.jdbc.driver.namedTypeAccessor.otypeFro@R_673_8156@(namedTypeAccessor.java:83)
        at Oracle.jdbc.driver.TypeAccessor.initMetadata(TypeAccessor.java:76)
        at Oracle.jdbc.driver.T4CCallableStatement.allocateAccessor(T4CCallableStatement.java:599)
        at Oracle.jdbc.driver.OracleCallableStatement.registerOutParameterInternal(OracleCallableStatement.java:201)
        at Oracle.jdbc.driver.OracleCallableStatement.registerOutParameter(OracleCallableStatement.java:240)
        at Oracle.jdbc.driver.OracleCallableStatementWrapper.registerOutParameter(OracleCallableStatementWrapper.java:1243)
        at com.zaxxer.hikari.pool.HikariProxyCallableStatement.registerOutParameter(HikariProxyCallableStatement.java)
        at org.springframework.jdbc.core.CallableStatementCreatorFactory$CallableStatementCreatorImpl.createCallableStatement(CallableStatementCreatorFactory.java:188)
        at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1090)
        at org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1147)
        at org.springframework.jdbc.core.simple.AbstractJdbcCall.executeCallinternal(AbstractJdbcCall.java:412)
        at org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:372)
        at org.springframework.jdbc.core.simple.SimpleJdbcCall.execute(SimpleJdbcCall.java:198)

不幸的是,我无法更改客户端数据库中的任何内容 :( 所以我无法更改声明 TYPE name_array IS table OF VARCHAR2(50) INDEX BY BINARY_IntegeR; 并且我需要在 java、spring boot 中构建一个应用程序。有没有办法做到这一点在 Oracle 上更改程序和包。

我做错了什么?提前致谢。

解决方法

其中之一是输出参数类型 TABLE OF VARCHAR2

您弄错了,其中一个是 TABLE OF VARCHAR2(50) INDEX BY BINARY_IntegeR,它是一个关联数组,您不能使用 JDBC 映射到这种类型。

参见 this answer 或 this answer。

  1. 您需要在 SQL 范围内使用 CREATE TYPE 定义数据类型(而不是在 pl/sqL 范围内,在包中),因为 JDBC 只能使用 SQL 定义的数据类型。
  2. 第 1 点的结果是 JDBC 不支持关联数组,因为它们是仅 pl/sqL 的数据类型,并且您需要使用集合(与 C# 不同,C# 只支持关联数组而不支持集合)。因此,您需要从类型中删除 INDEX BY 子句。

在包外声明类型:

CREATE TYPE name_array IS TABLE OF VARCHAR2(50);

然后从包中删除关联数组声明并改用新的集合类型。之后可能会有更多的错误需要调试;但它永远不会使用关联数组工作。

不幸的是,我无法更改客户端数据库中的任何内容 :( 所以我无法更改声明 TYPE name_array IS TABLE OF VARCHAR2(50) INDEX BY BINARY_IntegeR; 并且我需要在 java、spring boot 中构建一个应用程序。有没有办法做到这一点在 Oracle 上更改程序和包。

您可以尝试通过调用匿名 pl/sqL 块(反过来调用包)来将关联数组转换为 varray(例如 SYs.ODCIVARCHAR2LIST)来解决此问题:>

DECLARE
  v_name_assoc_array PACK1.NAME_ARRAY;
  v_name_list        SYs.ODCIVARCHAR2LIST := SYs.ODCIVARCHAR2LIST();
  v_idx              BINARY_IntegeR;
BEGIN
  PACK1.proc_filter_and_return_array( :p_name_in,v_name_assoc_array );

  v_idx := v_name_assoc_array.FIRST;
  WHILE v_idx IS NOT NULL LOOP
    v_name_list.EXTEND;
    v_name_list(v_name_list.COUNT) := v_name_assoc_array(v_idX);
    v_idx := v_name_assoc_array.NEXT(v_idX);
  END LOOP;

  :p_name_out_array := v_name_list;
END;
/
,

我是来展示代码的,因为 MTO 已经回答了我。 解决从 Java 调用匿名 pl/sqL 块并获得返回值的最佳解决方案。

我终于成功得到了下面的代码:

npm i react-currency-format

大佬总结

以上是大佬教程为你收集整理的使用 java SimpleJdbcCall 调用带有 out 参数类型“is table of varchar2”的过程 oracle全部内容,希望文章能够帮你解决使用 java SimpleJdbcCall 调用带有 out 参数类型“is table of varchar2”的过程 oracle所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。