java.sql.SQLException:从jdbc执行包级别类型的过程时,列类型无效

时间:2017-08-17 13:08:04

标签: java sql oracle procedure

问题描述: 我试图通过java代码调用存储在我的数据库中的过程。我想要调用的过程有一个参数类型为' MAP_VARCHAR' (我已将其定义为下面包中的类型)。

现在,我尝试从我的java代码执行此过程,但是传递参数是给java.sql.SQLException。

SQL包,向您展示如何创建SQL过程并键入

--------------------------------------------------------
--   Package Body TEST_PACKAGET
--------------------------------------------------------

  CREATE OR REPLACE EDITIONABLE PACKAGE BODY "TEST_PACKAGE" AS

  PROCEDURE PerformersRole(P_Performer_Map MAP_VARCHAR) AS
  BEGIN

        DBMS_OUTPUT.PUT_LINE('Hello ' || P_Performer_Map('Engineer'));

  END PerformersRole;

END TEST_PACKAGE;

/
--------------------------------------------------------
--   Package TEST_PACKAGE
--------------------------------------------------------

  CREATE OR REPLACE EDITIONABLE PACKAGE "TEST_PACKAGE" AS 

  /* TODO enter package declarations (types, exceptions, methods etc) here */ 
  TYPE MAP_VARCHAR IS TABLE OF VARCHAR(100) INDEX BY VARCHAR(100);

  PROCEDURE PerformersRole(P_Performer_Map MAP_VARCHAR);
END TEST_PACKAGE;

/

我的java代码

    public void executeProcedure(){

       CallableStatement statement = null;
        try {

/// Oracle Connection code should be here 
             Connection connection = connectionManager.createConnection();


            Hashtable newMap = new Hashtable();

            newMap.put("Engineer", "Hanson");
            newMap.put("Assistant", "Alice Kim");
            newMap.put("Supervisor", "James MaCoy");


            StringBuffer procedure = new StringBuffer("{call TEST_PACKAGE.PerformersRole(?) }");
            statement = connection.prepareCall(procedure.toString());
            statement.setInt(1, newMap );

            statement.execute();
        } catch (Exception ex) {


        } 

} 

我执行java代码时收到的错误是

java.sql.SQLException: Invalid column type
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:8761)
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8259)
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:9012)
    at oracle.jdbc.driver.OracleCallableStatement.setObject(OracleCallableStatement.java:4983)
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:230)

我缺少什么?!

提前感谢您的帮助

3 个答案:

答案 0 :(得分:0)

在Oracle 11.2中,无法使用jdbc中的包级别类型。并且无法在sql级别创建关联数组。

此代码将失败。

create  TYPE MAP_VARCHAR IS TABLE OF VARCHAR(100) INDEX BY VARCHAR(100);

一个例外是varchar的关联数组或binary_integer的数字索引。 Accessing PL/SQL Associative Arrays

答案 1 :(得分:0)

好吧,我花了一些时间试图弄清楚如何在ArkadiuszŁukasiewicz发表评论之后克服这个问题,因为他没有提供任何官方文件提及,我做了快速研究,似乎他的主张是合法的。
  
有两种方法可以解决从java访问SQL包级别类型的问题:

方法#1
Panser在以下URL中提供的答案 [https://stackoverflow.com/a/25989632/8477836][1]

你需要的只是构建SQL DECLARE ... BEGIN ... END块然后从你的java执行它。   
  
方法#2
我在单独的表中插入了我希望在我的过程中传递的级别类型(MAP_VARCHAR),然后在我的SQL包中,我创建了函数以使用我创建的表中的游标检索这些值并将返回的值存储到我的局部变量中的类型为(MAP_VARCHAR)

负责存储MAP_VARCHAR值

的函数
    FUNCTION GET_MAP_VARCHAR(P_PROCESS_ID NUMBER)
    RETURN MAP_VARCHAR IS
      LV_MAP_VARCHAR MAP_VARCHAR;
      LV_MAP_VARCHAR_TABLE_ROW EPAD_WF_RESD_PRFM_RLE%ROWTYPE;

        CURSOR C_GET_MAP_VARCHAR_ROWIS 
            SELECT * FROM TEST T
            WHERE T.TEST = P_PROCESS_ID;

  BEGIN

      FOR R_GET_MAP_VARCHAR_ROWIN C_GET_MAP_VARCHAR_ROWLOOP
        LV_MAP_VARCHAR(R_GET_MAP_VARCHAR_ROW .ROLE):= R_GET_MAP_VARCHAR_ROW.NAME;
      END LOOP;

    RETURN LV_MAP_VARCHAR;

  END GET_MAP_VARCHAR

我的新SQL程序应如下所示:

  CREATE OR REPLACE EDITIONABLE PACKAGE BODY "TEST_PACKAGE" AS

  PROCEDURE PerformersRole(P_ID Number) AS

    LV_Performer_Map MAP_VARCHAR
  BEGIN
    LV_Performer_Map MAP_VARCHAR= GET_MAP_VARCHAR(P_PROCESS_ID NUMBER);

        DBMS_OUTPUT.PUT_LINE('Hello ' || LV_Performer_Map('Engineer'));

  END PerformersRole;

希望这可以帮助任何因从Java

访问SQL包类型而遇到麻烦的人

答案 2 :(得分:0)

除了所有其他答案之外,我们遇到问题的场景是不同的。此错误不是您可以诊断的“确切”错误,但您必须假设它所抱怨的列是问题的线索。

我们在我们的一个数据库上遇到了同样的问题,问题是该查询有一个子查询,它期望一个项目,但被传递了一个数据数组。这抛出了主查询,因此它报告了该列的“无效列”,该列具有数据数组。检查以确保您的主查询未使用子查询或子查询。如果它使用子查询,则检查每个子查询并确保它们都按照您的期望返回。