2017-02-20 42 views
1

我想通過存儲過程將BLOB數據保存到Oracle數據庫。 (引用來自:Pass array from Java to Oracle: java.sql.SQLException: Fail to convert to internal representation:errorjava array blob數據插入到oracle db使用存儲過程(無法轉換爲內部表示:錯誤)

但我已經添加了BLOB列結構。 這是我的db腳本和java代碼。

--db代碼 - CREATE TABLE project_types( PROJ_ID VARCHAR2(10), proj_title VARCHAR2(10), proj_data BLOB ); /

CREATE OR REPLACE TYPE project_type AS OBJECT ( 
proj_id VARCHAR2(10), 
proj_title VARCHAR2(10), 
proj_data BLOB 
); 
/

CREATE OR REPLACE TYPE my_array AS TABLE OF project_type; 
/

CREATE OR REPLACE PROCEDURE add_projects(p_projects_array IN my_array) 
AS 
BEGIN 
IF p_projects_array IS NOT NULL THEN 
FOR v_i IN 1..p_projects_array.LAST 
LOOP 
INSERT INTO project_types 
VALUES (p_projects_array(v_i).proj_id, 
p_projects_array(v_i).proj_title, 
p_projects_array(v_i).proj_data); 
END LOOP; 
END IF; 
END; 
/

我已經加入BLOB數據列於表project_types和project_type TYPE, SturedProcedure。

--Table-- 
proj_data BLOB 

-- TYPE-- 
proj_data BLOB 

--StruedProcedure-- 
p_projects_array(v_i).proj_data 

- Java代碼 -

import java.sql.Array; 
import java.sql.Blob; 
import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.Struct; 

import javax.sql.rowset.serial.SerialBlob; 

import oracle.jdbc.OracleCallableStatement; 
import oracle.jdbc.driver.OracleConnection; 

public class calMilisecond { 

public static void main(String[] args) throws Exception { 
String url = "jdbc:oracle:thin:@localhost:1521:orcl"; 
String user = "testuser"; 
String password = "testuser123456"; 
Connection conn = DriverManager.getConnection(url, user, password);; 

OracleCallableStatement callStmt = null; 
try { 
    callStmt = (OracleCallableStatement)conn.prepareCall("{call add_projects(?)}"); 

    Blob blob1 = new SerialBlob(("test1").getBytes()); 
    Blob blob2 = new SerialBlob(("test2").getBytes()); 
    // create array holding values for ProjectType object's properties 
    Object[] project1 = new Object[] {"1", "Title 1", blob1}; 
    Object[] project2 = new Object[] {"2", "Title 2", null}; 

    // each struct is one ProjectType object 
    Struct structProject1 = conn.createStruct("PROJECT_TYPE", project1); 
    Struct structProject2 = conn.createStruct("PROJECT_TYPE", project2); 

    Struct[] structArrayOfProjects = {structProject1, structProject2}; 

    // array holding two ProjectType objects 
    Array arrayOfProjects = ((OracleConnection) conn).createOracleArray("MY_ARRAY", structArrayOfProjects); 

    callStmt.setArray(1, arrayOfProjects); 
    callStmt.execute(); 
    //conn.commit(); 

    System.out.println("Committed."); 
} catch (Exception e) { 
    if (conn != null) try { conn.rollback(); } catch (Exception ex) { System.out.println("Rollback failed."); } 
    throw e; 
} finally { 
    callStmt.close(); 
    conn.close(); 
}  

} 

- 錯誤代碼 - 當我嘗試斑點數據插入到數據庫

//錯誤發生。 //

Object [] project1 = new Object [] {「1」,「Title 1」,blob1};

Object [] project2 = new Object [] {「2」,「Title 2」,blob2};

java.sql.SQLException中:故障轉換爲內部
表示:誤差在oracle.jdbc.oracore.OracleTypeBLOB.toDatum(OracleTypeBLOB.java:69)在 oracle.jdbc.oracore.OracleType .toDatumInternal(OracleType.java:142)at oracle.sql.STRUCT。(())oracle.sql.STRUCT。(()。).database.toArray(StructDescriptor.java:1322)at oracle.sql.STRUCT。( STRUCT.java:136)at oracle.jdbc.driver.PhysicalConnection.createStruct(PhysicalConnection.java:8733)

- 當我嘗試使用NULL數據沒有錯誤 -

對象[] PROJECT1 =新對象[] { 「1」, 「標題1」,NULL};

Object [] project2 = new Object [] {「2」,「Title 2」,null};

請讓我知道如何解決這個問題。

謝謝。

回答

0

變化

Blob blob1 = new SerialBlob(("test1").getBytes()); 

BLOB blob1 = new BLOB((oracle.jdbc.OracleConnection)conn, ("test1").getBytes()); 

其中BLOBimport oracle.sql.BLOB;

而且你的代碼的其餘部分應該沒問題。

+0

此方法已棄用。請[看看這個](https://docs.oracle.com/database/121/JAJDB/oracle/sql/BLOB.html)。您必須使用'import java.sql.Blob;'而不是'import oracle.sql.BLOB;' – Jwags

+0

對於oracle 12c驅動程序來說的確如此。 –

0

我以爲我會發表一個答案,因爲我一直在掙扎着這一段時間。我有一個方法工作,這是類似於@Arkadiusz的答案,但它已被棄用。

我不知道爲什麼你會得到你的錯誤,但也許嘗試這種方法。

import java.sql.Blob; 
... 

public class MyClassDAO { 
    public static int sendBlobToDb(MyObject myObject) { 
     CallableStatement cstmt = null;  
     OutputStream os = null; 
     ObjectOutputStream oop = null; 
     Blob blob = null; 
     Connection conn = null; 
     index = 0; 
     int result = 0; 

     String sql = "begin " 
      + "insert into myTable " 
      + "(ITEMID, SOME_TEXT, SOME_NUMBER, THE_BLOB_FIELD) values " 
      + "(ITEMID_SEQ.nextval, ?, ?, empty_blob()) " 
      + "return THE_BLOB_FIELD into ?; " 
      + "end; "; 

     try { 
      conn = DriverManager.getConnection(url, user, password); 
      conn.setAutoCommit(false); 
      cstmt = conn.prepareCall(sql); 

      cstmt.setString(++index, myObject.getSomeText()); 
      cstmt.setLong(++index, myObject.getSomeNumber()); 
      cstmt.registerOutParameter(++index, java.sql.Types.BLOB); 
      cstmt.executeUpdate(); 

      blob = (Blob) cstmt.getBlob(index); 
      os = blob.setBinaryStream(1L); 
      oop = new ObjectOutputStream(os); 
      oop.writeObject(myObject.getListData()); 
     } catch(SQLException se) { 
      result = -1; 
      //log exception 
      try { 
       if(conn != null) { 
        conn.rollback(); 
       } 
      } catch(SQLException se2) { 
       //log exception 
      } 
     } catch(Exception e) { 
      result = -1; 
      //log exception 
     } finally { 
      try { 
       if (conn != null) { 
        conn.close(); 
       } 
       if (oop != null) { 
        oop.flush(); 
        oop.close(); 
       } 
       if (os != null) { 
        os.close(); 
       } 
       if (cstmt != null) { 
        cstmt.close(); 
       } 
      } catch(SQLException se) { 
       result = -1; 
       //log exception 
      } catch (Exception e) { 
       result = -1; 
       //log exception 
      } 
     } 

    return result; 
    } 
} 

我會使用這樣的發送對象的BLOB字段在Oracle中。我還沒有測試過,所以希望它可以工作。

相關問題