簡體   English   中英

調用從Java返回Oracle類型的PL / SQL函數

[英]Call PL/SQL function returning Oracle type from Java

我有一個PL / SQL函數,如下所示返回Oracle類型(PROCESSEXCLEFILEARGS)

FUNCTION PROCESS_FILE_INTERNAL
    (
      i_Filename VARCHAR2,
      i_EventType NUMBER
    ) 
    RETURN PROCESSEXCELFILEARGS

我必須從Java調用此函數,我的Java方法如下所示

OracleCallableStatement cstmt = null;
    try{  
        OracleDriver ora = new OracleDriver();
        DriverManager.registerDriver(ora);

        Connection connection = ora.defaultConnection();
        String call = "{ ? = call NEUTRINO_META.PKG_EXCEL.PROCESS_FILE_INTERNAL(?, ?) }";
                      cstmt = (OracleCallableStatement)connection.prepareCall(call);
                      cstmt.setQueryTimeout(1800);
                      cstmt.registerOutParameter(1, OracleTypes.OTHER, "NEUTRINO_META.PROCESSEXCELFILEARGS");
                      cstmt.setString(2, filename);
                      cstmt.setDouble(3, eventType);                          
                      cstmt.execute();

                      OracleObjects.ProcessExcelFileArgsobj = (OracleObjects.ProcessExcelFileArgs)cstmt.getObject(1);
                      connection.commit();


                }
    catch (SQLException e){
        WriteEventToDb(e.getMessage());
    }
    finally{
        if (cstmt != null){
            cstmt.close();
        }
    }

OracleObject.ProcessExcelFileArgs正在實現SQLData,並且正確實現了readSQl(..)和writeSQL(..)方法來讀取和寫入類型字段。

但是當我運行這個java方法時,我得到一個帶有'無效列類型:1111'消息的SQLException

任何人都可以讓我知道我采取的方法是否有任何錯誤,或者是否有任何其他方法來檢索返回oracle類型作為java對象。

編輯:

create or replace 
TYPE PROCESSEXCELFILEARGS FORCE AS OBJECT 
( 
  FullFilePath VARCHAR2(700),
  Filename VARCHAR2(200),
  Graph TYPEGRAPHDATA
)

請注意,TYPEGRAPHDATA是架構級別的另一個用戶定義的Oracle類型

謝謝

你的情況下使用oracle.sql.STRUCT類。 最簡單的例子:

在Oracle中:

create type type_dummy is object (
id int,
name varchar2(10)
)
/

create or replace function get_type_dummy
return type_dummy
is
begin
  return type_dummy(1,'ABCDe');
end;
/

在Java中:

class TypeDummy {
   public Long id;
   public String name;
}



    try {
        DriverManager.registerDriver ( new oracle.jdbc.driver.OracleDriver());
        Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@ods.fors.ru:1521:test","odh","odh");
        OracleCallableStatement cstmt = (OracleCallableStatement)conn.prepareCall("{ ? = call get_type_dummy }"); ;
        cstmt.registerOutParameter(1, OracleTypes.JAVA_STRUCT, "TYPE_DUMMY");
        cstmt.execute();
        oracle.sql.STRUCT td = (oracle.sql.STRUCT)cstmt.getObject(1);
        Object[] x = td.getAttributes();
        TypeDummy ntd = new TypeDummy();
        ntd.id = ((BigDecimal)x[0]).longValue();
        ntd.name = (String)x[1];
        System.out.println(ntd.id);
        System.out.println(ntd.name);                        
        cstmt.close();        
    }
...

輸出:

1
ABCDe

好吧,我設法通過使用以下代碼將返回的oracle類型作為java對象。

try{
Map rtn = connection.getTypeMap();
            rtn.put("NEUTRINO_META.PROCESSEXCELFILEARGS", Class.forName("OracleObjects.ProcessExcelFileArgs"));
            String call = "{ ? = call NEUTRINO_META.PKG_EXCEL.PROCESS_FILE_INTERNAL(?, ?) }";
                          cstmt = (OracleCallableStatement)connection.prepareCall(call);
                          cstmt.setQueryTimeout(1800);
                          cstmt.registerOutParameter(1, OracleTypes.STRUCT, "NEUTRINO_META.PROCESSEXCELFILEARGS");
                          cstmt.setString(2, filename);
                          cstmt.setDouble(3, eventType);                          
                          cstmt.execute();

                          ProcessExcelFileArgs args = (ProcessExcelFileArgs)cstmt.getObject(1, rtn);

        }
        catch (SQLException e){
            WriteEventToDb(e.getMessage());
        }        
        finally{
            if (cstmt != null){
                cstmt.close();
            }
        }

這由我的ProcessExcelFileArgs類實現了java.sql.SQLData,並通過添加到Oracletype到java類映射到連接類型映射。

你有一個Oracle類型是RECORD

TYPE my_type IS RECORD (
    foo      VARCHAR2 (12)
);

在oracle中你的函數返回一個PIPELINE

FUNCTION my_funtion (
    foo   VARCHAR2,
    bar   VARCHAR2
)
RETURN my_type PIPELINED

在java中,您可以使用表格函數 ,然后從ResultSet中檢索值

select * from table (URGP.PKG_AG_SIR_MEW.RECUPERARPERSONAPORNRODOC(?,?))

在這里,我看不出使用CallableStatement對象從包函數中獲取表數據的任何特殊需要。 相反,我們可以使用普通的sql查詢來包裝結果並將它們提取到普通的java結果集中。 這樣做,我們避免嘗試找到一個痛苦的解決方案來調整包函數(使用包級別類型),保持函數和包類型不變,以及繼續受益於使用未知的內部功能和流水線plsql函數的速度。 Panos Zafiropoulos。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM