无法将数组(BINARY_DOUBLE)从Java传递到Oracle存储过程?

时间:2015-07-14 21:07:02

标签: java oracle jdbc oracle11g

使用Java 1.7和Oracle 11.2数据库(使用Glassfish 3.1.2),我需要将大量java floatdouble数组放入Oracle存储过程中。有没有人这样做过?

如果我尝试传递整数数组,一切正常,如下所示:

create or replace TYPE TYPE_ARRAY_INT AS TABLE OF NUMBER; -- array of int
create or replace TYPE TYPE_ARRAY_SINGLE AS TABLE OF BINARY_FLOAT; -- array of single precision (e.g. float)
create or replace TYPE TYPE_ARRAY_DOUBLE AS TABLE OF BINARY_DOUBLE; -- array of double precision (e.g. double)

----ORACLE STORED PROCEDURE----
create or replace procedure SAVE_DATA (my_array IN TYPE_ARRAY_INT)
  as
  begin
     NULL;
  end SAVE_DATA;

 ----JAVA----
 public String SaveData() throws Exception {
   int[] intArray = new int[]{1,2,3};  // create integer array
   Connection conn = null;
   CallableStatement cs=null;
   try {
       Context context = new InitialContext();
       DataSource ds = (DataSource) context.lookup("jdbc/myOraclePool");
       OracleDataSource ods = ds.unwrap(OracleDataSource.class);
       conn = (OracleConnection) ods.getConnection();
       ArrayDescriptor des_int=ArrayDescriptor.createDescriptor("TYPE_ARRAY_INT", conn);
       cs = conn.prepareCall("{call save_data(?)}");
       ARRAY myArray_orcl = new ARRAY(des_int, conn, intArray);
      cs.setArray(1, myArray_orcl);
       cs.execute();
    } catch (Exception e) {
    } Finally {
          conn.close();
    }
    return "0";
  }

但如果我修改上面的代码以传递BINARY_FLOAT或BINARY_DOUBLE,我会收到错误java.sql.SQLException: Internal Error: Array is in inconsistent status

----ORACLE STORED PROCEDURE----
create or replace procedure SAVE_DATA (my_array IN TYPE_ARRAY_DOUBLE)
  as
  begin
     NULL;
  end SAVE_DATA;

 ----JAVA----
 public String SaveData() throws Exception {
   double[] doubleArray = new double[]{1,2,3};  // create double array
   Connection conn = null;
   CallableStatement cs=null;
   try {
       Context context = new InitialContext();
       DataSource ds = (DataSource) context.lookup("jdbc/myOraclePool");
       OracleDataSource ods = ds.unwrap(OracleDataSource.class);
       conn = (OracleConnection) ods.getConnection();
       ArrayDescriptor des_double=ArrayDescriptor.createDescriptor("TYPE_ARRAY_DOUBLE", conn);
       cs = conn.prepareCall("{call save_data(?)}");
       ARRAY myArray_orcl = new ARRAY(des_double, conn, doubleArray);
      cs.setArray(1, myArray_orcl);
       cs.execute();
    } catch (Exception e) {
    } Finally {
          conn.close();
    }
    return "0";
  }

任何人都知道为什么会这样吗?还是一个解决方法?

以下是关于对binary_float和binary_double的JDBC支持的Oracle 11.2数据库的相关部分:     http://docs.oracle.com/cd/E11882_01/java.112/e16548/oraint.htm#JJDBC28153

作为替代方案,我尝试替代:

cs.setPlsqlIndexTable(1, doubleArr, doubleArr.length, doubleArr.length, OracleTypes.BINARY_DOUBLE, 0);

但是这导致了运行时错误:

java.sql.SQLException: Invalid PL/SQL Index Table element type

我不明白,因为BINARY_DOUBLE是一个有效的OracleTypes()。 http://docs.oracle.com/cd/E11882_01/appdev.112/e13995/oracle/jdbc/OracleTypes.html

最后,我通过替换取代了Glassfish(以及它的JDBC连接池):

  OracleDataSource ods = new OracleDataSource();
  ods.setURL("jdbc:oracle:thin:id/pwd@192.168.xxx.xxx:nnnn:sid");
  conn = (OracleConnection) ods.getConnection();

但我仍然观察到相同的(初始)行为(例如数组处于不一致状态错误)。

1 个答案:

答案 0 :(得分:2)

尝试将数组作为BINARY_DOUBLE个对象的数组而不是double传递。课程BINARY_DOUBLE位于oracle.sql包中。

double[]数组转换为BINARY_DOUBLE[]数组非常简单:

   BINARY_DOUBLE[] binDoubles = new BINARY_DOUBLE[doubleArray.length];
   for (int i = 0; i < doubleArray.length; ++i) {
       binDoubles[i] = new BINARY_DOUBLE(doubleArray[i]);
   }

完成此操作后,请从ARRAY而不是binDoubles创建doubleArray

我能够使用普通JDBC连接到数据库的独立控制台程序重现您的错误,然后尝试调用您的存储过程。当我进行上述更改时,错误消失了,我可以调用存储过程。

cs.setPlsqlIndexTable的调用将失败,因为此方法仅适用于PL / SQL索引表,但您的类型是嵌套表。