gpt4 book ai didi

java - 如何在oracle中获取一个表作为输出参数

转载 作者:塔克拉玛干 更新时间:2023-11-01 22:50:36 26 4
gpt4 key购买 nike

我正在尝试将 oracle 过程调用的输出参数强制转换为一个对象。它不起作用,因为 - 据我了解 - 我需要定义一个 map ,它告诉方法如何转换它。如果 map 是空的或未正确填充,则它默认为 STRUCT 类型的 Objekt - 这在我的情况下是错误的。

我已经构建了一个示例,它应该可以说明问题:

-- Procedure in database
PROCEDURE myprocedure (
inputParam IN VARCHAR2 (4),
outputOne OUT outputOneSQLType
outputTwo OUT outputTwoSQLType);

-- inside of a package
inside a package mypackage

-- first type
create or replace
TYPE outputOneSQLType IS TABLE OF tableOneExample

-- table of type
create or replace
TYPE tableOneExample AS OBJECT (
somethingOne VARCHAR2 (4)
,somethingTwo NUMBER (12)
)

//java from here

import oracle.jdbc.OracleCallableStatement;
import oracle.jdbc.OracleTypes;
import oracle.jdbc.oracore.OracleTypeADT;
import oracle.sql.STRUCT;
...
oracle.jdbc.driver.OracleConnection oracleConn = (oracle.jdbc.driver.OracleConnection) con.getMetaData().getConnection();
final OracleCallableStatement storedProc = (OracleCallableStatement)oracleConn.prepareCall("{call mypackage.myprocedure("+
":inputParam, :outputOne, :outputTwo)}");

storedProc.setString("inputParam", "SomeValue");

storedProc.registerOutParameter("outputOne", OracleTypes.STRUCT, "OUTPUTONESQLTYPE");
storedProc.registerOutParameter("outputTwo", OracleTypes.STRUCT, "OUTPUTTWOSQLTYPE");

storedProc.execute();

//So far so good

//now I am lost - I need to define the map to get the object?
//What should be inside the map?
Hashtable newMap = new Hashtable();

newMap.put("outputOneSQLType", ?????.class);

//If the map is empty, it defaults to STRUCT...
final STRUCT myObject = (STRUCT)storedProc.getObject("somethingOne",newMap);
// myObject.getBytes() gives me an object... but I cannot cast it to anything

由于错误的 map ,我不能使用像这样的东西:

final MyClass myObject =  (MyClass)storedProc.getObject("somethingOne",newMap);   

我应该如何填充 map ?

编辑 1

oracle 数据库中的条目不能更改。我只是被允许使用它们。为此

stmt.registerOutParameter(2, java.sql.Types.ARRAY, "OUTPUTONESQLTYPE"); 

不起作用。因为一旦我不使用“OracleTypes.STRUCT”就会抛出异常。似乎在 outputOneSQLType 内部有一个类型为“OracleTypeCOLLECTION”的对象

当我尝试

 Hashtable newMap = new Hashtable();
newMap.put("outputOneSQLType",OracleTypeCOLLECTION.class);
final OracleTypeCOLLECTION myObject = (OracleTypeCOLLECTION)storedProc.getObject("somethingOne",newMap);

我得到一个异常:InstantiationException: oracle.jdbc.oracore.OracleTypeCOLLECTION

@DazzaL:我将尝试定义一个 SQLDATA 接口(interface)。也许这就是解决方案

解决方案

  1. 准备好的语句应该类似于“begin package.procedure(...); end;”并且“{call package.procedure(...)})
  2. 需要一个 SQLData 接口(interface)。

@DazzaL:你统治!谢谢。

最佳答案

你必须定义一个 sqldata 对象来映射它。

文档:http://docs.oracle.com/cd/E11882_01/java.112/e16548/oraarr.htm#JJDBC28574

例如:

SQL> create or replace TYPE tableOneExample AS OBJECT (
2 somethingOne VARCHAR2 (4)
3 ,somethingTwo NUMBER (12)
4 );
5 /

Type created.

SQL> create or replace TYPE outputOneSQLType IS TABLE OF tableOneExample;
2 /

Type created.

SQL>
SQL> create or replace PROCEDURE myprocedure (
2 inputParam IN VARCHAR2,
3 outputOne OUT outputOneSQLType)
4 as
5 begin
6 outputOne := outputOneSQLType(tableOneExample('a', 1), tableOneExample('b', 2));
7 end;
8 /

Procedure created.

现在我们定义 SQLDATA 接口(interface):

import java.sql.*;

public class TestArr implements SQLData
{
private String sql_type;

public String attrOne;
public int attrTwo;

public TestArr()
{
}
public TestArr (String sql_type, String attrOne, int attrTwo)
{
this.sql_type = sql_type;
this.attrOne = attrOne;
this.attrTwo = attrTwo;
}

// define a get method to return the SQL type of the object
public String getSQLTypeName() throws SQLException
{
return sql_type;
}

// define the required readSQL() method
public void readSQL(SQLInput stream, String typeName)
throws SQLException
{
sql_type = typeName;

attrOne = stream.readString();
attrTwo = stream.readInt();
}
// define the required writeSQL() method
public void writeSQL(SQLOutput stream)
throws SQLException
{
stream.writeString(attrOne);
stream.writeInt(attrTwo);
}
}

确保流写入/读取的输入和顺序与您的 oracle 类型相同,因为任何不一致都会导致内部表示错误。

然后在主类中,您将其映射如下:

CallableStatement stmt = conn.prepareCall("begin myprocedure(?,?); end;");
stmt.setString(1, "foo");
stmt.registerOutParameter(2, java.sql.Types.ARRAY, "OUTPUTONESQLTYPE"); // YOUR ARRAY TYPE (TO MATCH THE API OUTPUT), NOT OBJECT
stmt.execute();
Array arr = stmt.getArray (2);
Map map = conn.getTypeMap();
map.put("TABLEONEEXAMPLE", Class.forName("TestArr")); // YOUR OBJECT TYPE, NOT ARRAY.
Object[] values = (Object[]) arr.getArray();
for (int i=0; i < values.length; i++)
{
TestArr a = (TestArr)values[i];
System.out.println("somethingOne: " + a.attrOne);
System.out.println("somethingTwo: " + a.attrTwo);
}

结果bieng:

M:\Documents\Sample Code\1>javac TestArr.java

M:\Documents\Sample Code\1>javac ArrayTest.java
Note: ArrayTest.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

M:\Documents\Sample Code\SQLComplexArray>java ArrayTest
Opening Oracle connection...done.
somethingOne: a
somethingTwo: 1
somethingOne: b
somethingTwo: 2

关于java - 如何在oracle中获取一个表作为输出参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13801183/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com