2017-03-09 3 views
0

다음을 사용하여 Oracle 데이터베이스에서 사용자 정의 형식을 만들었습니다. 첫 번째는 레코드 유형 (행과 유사)이고 두 번째는 레코드 유형을 사용하여 구성된 테이블 유형입니다.테이블 형식의 저장 프로 시저를 IN 매개 변수로 사용하여 Varchar2 데이터를 삽입 할 수 없습니다.

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 코드입니다. 우리가 자바의 main 메소드를 실행하면 위의와

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(); 
     } 
    } 

은, 마지막으로, ID를 삽입하지만, 의외로하지 설명.

enter image description here

참고 : 위의 샘플 코드 조각 문제를 설명하기 위해 가져옵니다. 구문에는 약간의 사소한 문제가있을 수 있지만 프로젝트에서 직면 한 문제를 정확히 복제합니다.

+0

우리가 찾을 수없는 근본적인 문제가있을 수 있습니다. 모든 통찰이나 제안은 높이 평가됩니다. – Kali

+0

Java 코드 및 쿼리 결과를 텍스트로 게시하십시오 ([not images] (https://meta.stackoverflow.com/questions/285551/why-may-i-not-upload-images-of-code-on-so). -wind-asking-a-question/285557 # 285557). 원격 데스크톱의 텍스트를 복사 할 수없는 이유는 무엇입니까? –

+0

코드를 다시 작성하면 Oracle 11gR2 및 JDK1.7에서 정상적으로 작동하는 것 같습니다. (예약어를 피하기 위해 desc에서 descr로 객체 필드 이름을 변경해야하지만 그렇지 않으면 나는 그것이 동일하다고 믿는다; cs 또는 연결을 닫지는 않지만 문제와 관련이 없다는 것을 알아 차렸다). 어쩌면 이상한 행동을 일으키는 JDBC 드라이버/데이터베이스 불일치가 있습니까? 그렇지 않으면 문제를 복제하기 위해 실행할 수있는 [MCVE] (https://stackoverflow.com/help/mcve)를 만드십시오. –

답변

0

, 나는이 문제 뒤에 이유를 게시 할 생각. orai18n.jar 인 classpath에 누락 된 라이브러리가 있기 때문에 텍스트 데이터가 데이터베이스로 업데이트되지 않고 발생했습니다.

그래서 이러한 문제를 피하려면 드라이버와 언어 지원 Jar 파일을 모두 추가해야합니다.

0

코드에서 약간의 변경 - java.sql.Array 대신 oracle.sql.ARRAY을 사용하고 Connection.setObject() 대신 OracleConnection.setARRAYAtName()을 사용하여 매개 변수를 바인딩합니다.

(참고 :이 오라클 11.2.0.1 오라클 드라이버 ojdbc6.jar 사용했다)

오라클 설치을;

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){} 
    } 
    } 
} 
+0

감사합니다. @ MT0. 처음에는'java.sql.Array' 대신'oracle.sql.ARRAY'를 시도했습니다. 그것은 우리를 위해 일하지도 않았다. 그러나 이러한 클래스는 이제 더 이상 사용되지 않으므로 (ref : https://docs.oracle.com/database/121/JAJDB/oracle/sql/ARRAY.html) java.sql 클래스로 바뀌 었습니다.그래도 코드에서 접근 방식의 변화는 거의 볼 수 없습니다. 그 (것)들을 시도하고 새롭게 할 것이다. – Kali

+0

코드를 링크 한 페이지에서 'java.sql.Array objs = ((oracle.jdbc.OracleConnection) con) .createOracleArray ("TAB_TYPE", new Object [] [] {o1, o2, ("(OracleCallableStatement) st) .setArrayAtName ("arr ", objs);'... 그러나 Oracle 12 인스턴스를 사용하지 않아도됩니다. (그리고' createOracleArray'는'ojdbc6'에서 "Unsupported Feature"예외를 던집니다. 그러나 그것은 당신이 사용하고있는 코드와 거의 같습니다. – MT0

관련 문제