调用PL/SQL功能从Java返回Oracle类型



i具有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 class。最简单的例子:

在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();
            }
        }

这是我的ProcessExcelfileAreargs类实现的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中,您可以使用表功能,然后从结果集中检索值

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

在这里,我看不到使用CallablStatement对象从软件包函数获取后表数据的任何特定需要。取而代之的是,我们可以使用普通的SQL查询来包装结果并将其获取到普通的Java结果集中。这样做,我们避免尝试找到一个痛苦的解决方案来调整包装功能(使用包装级类型),使功能和软件包类型完好无损,并继续受益于使用管道插入的PLSQL功能的不知不见的内部功能和速度。Panos Zafiropoulos。

最新更新