使用 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.otypeFromName(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 answerthis 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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?