无法使用表类型为IN参数的存储过程插入Varchar2数据

时间:2017-03-09 11:58:12

标签: oracle jdbc

我们使用以下内容在Oracle数据库中创建用户定义的类型。第一个是记录类型(类似于一行),第二个是使用记录类型构造的表类型。

create or replace type REC_TYPE as object(bid number, bdesc varchar2(100));
/ 
create or replace type TAB_TYPE as table of REC_TYPE;
/

下面介绍用于向表中插入数据的表和过程。

create table BOM (bom_id number, bom_desc varchar2(100));
/
create or replace procedure pBOM (tIn IN TAB_TYPE, res OUT VARCHAR2)
is
begin
  for i in 1..tIn.count loop
      insert into BOM values(tIn(i).bid, tIn(i).bdesc);
  end loop;
end; 
/

以下是用于使用JDBC调用过程的java代码。

public  void method()   throws ClassNotFoundException, SQLException {

        Class.forName("oracle.jdbc.driver.OracleDriver");

        try (Connection connection = DriverManager.getConnection("<jdbc_url>", "<user>", "<password>")) {   


            connection.setAutoCommit(false);

            Object[] attributes = new Object[]{1, "test bom"};
            Struct rec= connection.createStruct("REC_TYPE", attributes);
            Struct[] tab =  new Struct[]{ rec };
            Array tabArr = ((OracleConnection)connection).createOracleArray("TAB_TYPE", tab);

            CallableStatement cs = connection.prepareCall("{call pBOM(?,?)}");
            cs.setObject(1, tabArr);
            cs.registerOutParameter(2, Types.VARCHAR);
            cs.executeUpdate();

            connection.commit();
            tabArr.free();
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

有了上述内容,最后当我们在java中运行main方法时,它会插入ID,但令人惊讶的是没有描述。

enter image description here

注意:上面的示例代码片段用于解释问题。语法中可能存在一些小问题,但它完全复制了我们在项目中面临的问题。

2 个答案:

答案 0 :(得分:0)

代码中的一些小变化 - 使用oracle.sql.ARRAY而不是java.sql.Array,然后使用OracleConnection.setARRAYAtName()而不是Connection.setObject()来绑定参数。

(注意:使用Oracle Driver ojdbc6.jar和Oracle 11.2.0.1一起工作)

Oracle设置;

CREATE TYPE rec_type AS OBJECT( id NUMBER, descr VARCHAR2(100) );
/
CREATE TYPE tab_type AS TABLE OF rec_type;
/
CREATE TABLE bom OF rec_type;
/
CREATE PROCEDURE pBom( t IN tab_type )
IS
BEGIN
  FORALL i IN INDICES OF t
    INSERT INTO bom VALUES t(i);
END;
/

<强>爪哇

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import oracle.jdbc.OracleCallableStatement;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;

public class TestDatabase2 {
  public static void main(String args[]){
    Connection con = null;
    try{
      Class.forName("oracle.jdbc.OracleDriver");

      con = DriverManager.getConnection(
        "jdbc:oracle:thin:@localhost:1521:XE",
        "username",
        "password"
      );

      ArrayDescriptor des = ArrayDescriptor.createDescriptor("TAB_TYPE", con);

      Object[] o1 = { 1, "ABC" };
      Object[] o2 = { 3, "DEF" };
      Object[] o3 = { 2, "GHI" };

      ARRAY objs = new ARRAY( des, con, new Object[][]{ o1, o2, o3 } );

      CallableStatement st = con.prepareCall("{ call pBOM( :arr )}");

      ((OracleCallableStatement) st).setARRAYAtName( "arr", objs );

      st.execute();
    } catch(ClassNotFoundException | SQLException e) {
      System.out.println(e);
    } finally {
       try {
         if ( con != null )
         {
           con.close();
         }
       } catch ( SQLException e ){}
    }
  }
}

答案 1 :(得分:0)

由于我无法看到更多答案,我想发布问题背后的原因。发生这种情况的原因是类路径中缺少了库orai18n.jar,没有它,文本数据没有更新到数据库。

因此我们需要添加驱动程序以及语言支持Jars以避免此类问题。