使用Oracle对象参数调用Oracle存储过程

4
我将oracleojdbc版本从11.1.0.2升级到12.1.0.2。我想将一组oracle对象类型作为参数传递给一个oracle procedure。这个过程在oracle端需要两个varchar2参数。例如,我发送了三个对象作为一个键值对数组,并且oracle接受了这些对象。我的问题是,调用过程时,varchar2类型的参数为空。
下面是我尝试过的代码:
OracleConnection oraconn = conn.unwrap(OracleConnection.class);
Struct[] paramStructArray = new Struct[3];
paramStructArray[0] = oraconn.createStruct("KEY_VALUE_ENTRY",new Object[]{"key1","value1"});
paramStructArray[1] = oraconn.createStruct("KEY_VALUE_ENTRY",new Object[]{"key2","value2"});
paramStructArray[2] = oraconn.createStruct("KEY_VALUE_ENTRY",new Object[]{"key3","value3"});
Array array = oraconn.createOracleArray("KEY_VALUE_MAP", paramStructArray);

CallableStatement cstmt = getStatement(Statement.REGISTER_REQUEST);
cstmt.setString(1, requestId);
cstmt.setArray(2, array);
cstmt.execute();

这是我的Java代码,这里还有我的Oracle 对象


CREATE OR REPLACE TYPE "KEY_VALUE_ENTRY"  AS
OBJECT (
  key VARCHAR2(32),
  val VARCHAR2(2048)
);


CREATE OR REPLACE TYPE "KEY_VALUE_MAP"    AS
TABLE OF key_value_entry;

和我的程序
PROCEDURE register_request_(p_request_id IN varchar2
                             ,p_params     IN key_value_map) AS
  BEGIN
    IF p_params IS NOT NULL THEN
      INSERT INTO test_table
        (request, NAME, VALUE)
        SELECT test_seq.nextval
              ,t.key
              ,t.val
          FROM TABLE(CAST(p_params AS key_value_map)) t;
      COMMIT;
  END IF;
  EXCEPTION
    WHEN OTHERS THEN
      RAISE;
  END;

我正在Oracle端获取3个KEY_VALUE_ENTRY类型的对象,但是这些对象的keyval字段都为空。我无法弄清楚我做错了什么。


在升级之前,这个工作是否按预期运行?请检查一下,因为我不知道它是否按照预期运行。 - MNM
你可能需要重写很多代码,我猜测。我的建议是将代码恢复到工作状态,然后逐步替换每个部分,并在此过程中进行调试。 所以,做出更改,进行调试,再做出更改,再进行调试。 这有点繁琐,但我认为你可以找到问题所在。 - MNM
这是我能找到的最好的答案,但我仍然不认为它回答了你的问题。 https://stackoverflow.com/questions/37160300/how-to-pass-list-from-java-to-oracle-procedure - MNM
这正是我想要的并且正在尝试同样的方法,但由于某些原因它不起作用。https://dev59.com/BHjZa4cB1Zd3GeqPkPfU - Gog1nA
这两个变量,它是在发送 null 还是只接收 null? - MNM
显示剩余2条评论
2个回答

2

有一个编码问题,其中Java给出并且Oracle接受这些值,在我的classpath中添加orai18n.jar后一切正常。

"Original Answer"的翻译是“最初的回答”。


0

我尝试了这段代码,没有将orai18n.jar添加到类路径中,它按预期工作。我保留了数据库方法。

public void insertTable(List<KeyValueObj> list, Connection conn)
            throws SQLException {
        String str = "{call Test_schema.Test_pkg.Register_Request(?,?)}";
        OracleCallableStatement statement = null;
        OracleConnection oraConn = null;
        String requestId = "111";
        try{
            oraConn = conn.unwrap(OracleConnection.class);
            statement = (OracleCallableStatement) oraConn.prepareCall(str);
            statement.setObject(2, getOracleRowObjectList(list, oraConn));
            statement.setString(1,requestId);
            statement.execute();
        }finally {
            try {
                statement.close();
                } catch (Exception e) {

            }
        }

    }

     private Array getOracleRowObjectList(List<KeyValueObj> list, OracleConnection conn) throws SQLException{
        String type = "Test_schema.KEY_VALUE_MAP";
        Struct[] structList = new Struct[list.size()];

        for(int i=0;i<list.size();i++){
            structList[i] = getOracleRowObject(conn, list.get(i));
        }

        return conn.createOracleArray(type, structList);
    }


    private Struct getOracleRowObject(OracleConnection conn, KeyValueObj obj) throws SQLException{
        String typeRow = "Test_schema.KEY_VALUE_ENTRY";
        return conn.createStruct(typeRow,
                new Object[]{ obj.getKey(),
                              obj.getValue(),

        });
    }

KeyValueObj类

public class KeyValueObj {
    private String key;
    private String value;

    public KeyValueObj(String key, String value) {
        super();
        this.key = key;
        this.value = value;
    }

    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }   

}

希望这能帮助到遇到同样问题的人。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接