java - 使用java以表对象作为输入调用oracle存储过程

标签 java oracle java-stored-procedures

我尝试使用 4 个参数 1 作为自定义类型表的输入来调用 Oracle 存储过程,并收到以下错误 和 PriceInBundle_Input_Table 是一个具有两个元素的对象 Material 编号 nvarchar2(22), 捆绑编号 nvarchar2(22)

java.sql.SQLException: ORA-03115: unsupported network datatype or representation

    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445)
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
    at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879)
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:450)
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
    at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
    at oracle.jdbc.driver.T4CCallableStatement.doOall8(T4CCallableStatement.java:204)
    at oracle.jdbc.driver.T4CCallableStatement.executeForRows(T4CCallableStatement.java:1034)
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1329)
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3584)
    at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:3685)
    at oracle.jdbc.driver.OracleCallableStatement.execute(OracleCallableStatement.java:4694)
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1088)
    at  com.wincash.test.service.PriceInBundle.getPriceInBundle(PriceInBundle.java:33)
    at com.wincash.test.Wincash.main(Wincash.java:10)

这是我尝试调用的存储过程

      create or replace PROCEDURE        GET_PRICE_IN_BUNDLE(
    P_IN_PriceInBundle_Input IN PriceInBundle_Input_Table,
    P_OUT_PriceInBundle_Output OUT PriceInBundle_Output_Table,
    P_OUT_RETURN_CODE OUT NUMBER,
    P_OUT_RETURN_MESSAGE OUT VARCHAR2 )
AS
  V_PRICE         NUMBER:=-1;
  V_Count_Article NUMBER:=-1;
  V_Count_Bundle  NUMBER:=-1;
  V_Count_Matset  NUMBER :=-1;
BEGIN
  P_OUT_RETURN_CODE          := -200;
  P_OUT_RETURN_MESSAGE       :='Initial';
  P_OUT_PriceInBundle_Output := PriceInBundle_Output_Table();
  FOR item_record_index IN P_IN_PriceInBundle_Input.FIRST .. P_IN_PriceInBundle_Input.LAST
  LOOP
    P_OUT_PriceInBundle_Output.EXTEND ;
    P_OUT_PriceInBundle_Output(item_record_index)                := PriceInBundle_Output_Record('','',-1,-1,'');
    P_OUT_PriceInBundle_Output(item_record_index).MaterialNumber := P_IN_PriceInBundle_Input(item_record_index).MaterialNumber ;
    P_OUT_PriceInBundle_Output(item_record_index).BundleNumber   := P_IN_PriceInBundle_Input(item_record_index).BundleNumber ;
    V_PRICE                                                      :=-1;
    BEGIN
      SELECT MAX(PRICE)
      INTO V_PRICE
      FROM matset
      WHERE compid IN
        (SELECT gid
        FROM material
        WHERE matno= P_IN_PriceInBundle_Input(item_record_index).MaterialNumber
        AND status<>'D'
        )
      AND matid IN
        (SELECT gid
        FROM material
        WHERE matno= P_IN_PriceInBundle_Input(item_record_index).BundleNumber
        AND status<>'D'
        )
      AND status                                                   <>'D';
      IF V_PRICE                                                   IS NOT NULL THEN
        P_OUT_PriceInBundle_Output(item_record_index).Price        := V_PRICE;
        P_OUT_PriceInBundle_Output(item_record_index).ResultCode   :=0;
        P_OUT_PriceInBundle_Output(item_record_index).ResultMessage:='SUCCESS';
      ELSE
        SELECT COUNT(*)
        INTO V_Count_Matset
        FROM matset
        WHERE compid IN
          (SELECT gid
          FROM material
          WHERE matno= P_IN_PriceInBundle_Input(item_record_index).MaterialNumber
          AND status<>'D'
          )
        AND matid IN
          (SELECT gid
          FROM material
          WHERE matno= P_IN_PriceInBundle_Input(item_record_index).BundleNumber
          AND status<>'D'
          )
        AND status      <>'D';
        IF V_Count_Matset>0 THEN
          SELECT MAX(price)
          INTO V_PRICE
          FROM material
          WHERE matno                                                 =P_IN_PriceInBundle_Input(item_record_index).MaterialNumber
          AND status                                                  ='A';
          P_OUT_PriceInBundle_Output(item_record_index).Price        := V_PRICE;
          P_OUT_PriceInBundle_Output(item_record_index).ResultCode   :=0;
          P_OUT_PriceInBundle_Output(item_record_index).ResultMessage:='Success';
        ELSE
          SELECT COUNT(*)
          INTO V_Count_Article
          FROM material
          WHERE matno                                                   = P_IN_PriceInBundle_Input(item_record_index).MaterialNumber
          AND status                                                    ='A';
          IF V_Count_Article                                            =0 THEN
            P_OUT_PriceInBundle_Output(item_record_index).Price        := -1;
            P_OUT_PriceInBundle_Output(item_record_index).ResultCode   := -2;
            P_OUT_PriceInBundle_Output(item_record_index).ResultMessage:='Wrong Article Number';
          ELSE
            SELECT COUNT(*)
            INTO V_Count_Bundle
            FROM material
            WHERE matno                                                   = P_IN_PriceInBundle_Input(item_record_index).BundleNumber
            AND status                                                    ='A';
            IF V_Count_Bundle                                             =0 THEN
              P_OUT_PriceInBundle_Output(item_record_index).Price        := -1;
              P_OUT_PriceInBundle_Output(item_record_index).ResultCode   := -3;
              P_OUT_PriceInBundle_Output(item_record_index).ResultMessage:='Wrong Bundle Number';
              ELSE
               P_OUT_PriceInBundle_Output(item_record_index).Price        := -1;
              P_OUT_PriceInBundle_Output(item_record_index).ResultCode   := -4;
              P_OUT_PriceInBundle_Output(item_record_index).ResultMessage:='Article does not belong to bundle';
            END IF;
          END IF;
        END IF;
      END IF;
    EXCEPTION
    WHEN NO_DATA_FOUND THEN
      P_OUT_PriceInBundle_Output(item_record_index).Price         := -1;
      P_OUT_PriceInBundle_Output(item_record_index).ResultCode    := -4 ;
      P_OUT_PriceInBundle_Output(item_record_index).ResultMessage := 'Invalid Input,No price found' ;
    WHEN OTHERS THEN
      P_OUT_PriceInBundle_Output(item_record_index).Price         := -1;
      P_OUT_PriceInBundle_Output(item_record_index).ResultCode    := -100 ;
      P_OUT_PriceInBundle_Output(item_record_index).ResultMessage :='UNKNOWN ERROR ' ||SQLERRM ;
    END ;
  END LOOP;
  P_OUT_RETURN_CODE    := 0 ;
  P_OUT_RETURN_MESSAGE := 'Success' ;
EXCEPTION
WHEN OTHERS THEN
  P_OUT_RETURN_CODE    := -100 ;
  P_OUT_RETURN_MESSAGE :='UNKNOWN ERROR ' ||SQLERRM ;
END;

我尝试使用以下java代码进行调用

import com.wincash.test.config.DBConnection;

import oracle.jdbc.OracleCallableStatement;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;

public class PriceInBundle {
    private static Logger logger= Logger.getLogger(PriceInBundle.class);
    private static Connection conn=null;
    private static OracleCallableStatement callStatement=null;

    public Boolean getPriceInBundle() {
        Boolean rs=Boolean.FALSE;
        conn=DBConnection.getConnection();
        try {
            Object [] table= new Object[2];

            ArrayDescriptor priceInBundleTable= ArrayDescriptor.createDescriptor("PRICEINBUNDLE_INPUT_TABLE", conn);
            ARRAY priceInTable= new ARRAY(priceInBundleTable, conn, table);
            callStatement=(OracleCallableStatement)conn.prepareCall("{call GET_PRICE_IN_BUNDLE(?,?,?,?)}");
            callStatement.setARRAY(1, priceInTable);
            callStatement.registerOutParameter(2, java.sql.Types.ARRAY);
            callStatement.registerOutParameter(3, java.sql.Types.NUMERIC);
            callStatement.registerOutParameter(4, java.sql.Types.VARCHAR);

            rs=callStatement.execute();
        } catch (SQLException e) {
//          logger.info(e.getMessage());
            e.printStackTrace();
        }finally {
            try {
                conn.close();
                callStatement.close();
            } catch (SQLException e) {
                logger.info(e.getMessage());
            }

        }
        return rs;
    }
}

请大家多多支持

最佳答案

我找到了解决方案here只需将 oracle 自定义类型添加到输出参数,如以下代码 将此代码更改为

callStatement.registerOutParameter(2, java.sql.Types.ARRAY);

callStatement.registerOutParameter(2, java.sql.Types.ARRAY,"PRICEINBUNDLE_OUTPUT_TABLE");

感谢 Marmite Bomber 解决了问题对于他的评论

关于java - 使用java以表对象作为输入调用oracle存储过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54852543/

相关文章:

java - 为什么我的 JToggleButton 不接受我的 setDisabledIcon()?

mysql - 创建将 SYS_REFCURSOR 作为输出参数的 mysql 过程时出错

java - AbsoluteLayout 在 NetBeans 中丢失

java - 吞吐量的 HTTP 客户端 - Netty 与 Apache HttpAsyncClient

Ruby OCI8 和 Oracle 存储过程 - 如何访问作为引用游标的bind_param?

oracle - 如何在Grails中删除子域行

使用byte []在oracle中的java用户定义函数

mysql - 为自动递增字段设置起始值的存储过程

java - 获取通用类参数的类名

oracle - 跟踪 Oracle 表之间的路径?