2011-08-21 8 views
8

W obiektowym PL/SQL mogę dodawać procedury członkowskie i funkcje do typów. Przykładem są tu:Wywołaj oparte na obiektach Oracle procedury PL/SQL od JDBC

create type foo_type as object (
    foo number, 

    member procedure proc(p in number), 
    member function func(p in number) return number 
); 

create type body foo_type as 
    member procedure proc(p in number) is begin 
    foo := p*2; 
    end proc; 

    member function func(p in number) return number is begin 
    return foo/p; 
    end func; 
end; 

Od: http://www.adp-gmbh.ch/ora/plsql/oo/member.html

w PL/SQL, mogę wtedy zadzwonić do tych procedur członków/funkcje, takie jak ten:

declare 
    x foo_type; 
begin 
    x := foo_type(5); 
    x.proc(10); 
    dbms_output.put_line(x.func(2)); 
end; 

Jak mogę to zrobić z Kalendarium JDBC w CallableStatement? Nie mogę tego łatwo znaleźć w dokumentacji.

UWAGA: Jest to jedna z możliwości, inline konstruktora typu:

CallableStatement call = c.prepareCall(
    " { ? = call foo_type(5).func(2) } "); 

Ale co szukam jest mniej więcej tak (za pomocą java.sql.SQLData jako parametr):

CallableStatement call = c.prepareCall(
    " { ? = call ?.func(2) } "); 

Również funkcje składowe, procedury mogą modyfikować obiekt. Jak mogę odzyskać zmodyfikowany obiekt w Javie?

+0

jest podstawą Twojego pytania naprawdę "Jak wywołać funkcję członka"? A może raczej "Jak przekazać obiekt jako parametr"? – Codo

+0

@Codo: Rdzeniem jest odzyskiwanie wyników funkcji członków (przykładowa odpowiedź udzielona przez Vincenta Malgrat) oraz sposób pobierania potencjalnie zmodyfikowanego obiektu. –

Odpowiedz

4

W jdbc można analizować i wykonywać bloki PL/SQL ze zmiennymi out. Można przygotować wpłacone oświadczenie takie jak:

declare 
    x foo_type; 
begin 
    x := foo_type(5); 
    x.proc(10); 
    ? := x.func(2); 
end; 

Następnie można użyć CallableStatement.registerOutParameter i po instrukcja została wykonana, należy zastosować odpowiednią get funkcji pobrać wartość.

Można bezpośrednio uzyskać dostęp do typu FOO_TYPE bezpośrednio w Javie, ale czy naprawdę chcesz to zrobić? Poniżej znajduje się przykład pracy:

SQL> create or replace and compile java source named "TestOutParam" as 
    2 import java.sql.*; 
    3 import oracle.sql.*; 
    4 import oracle.jdbc.driver.*; 
    5 
    6 public class TestOutParam { 
    7 
    8  public static int get() throws SQLException { 
    9 
10  Connection conn = 
11   new OracleDriver().defaultConnection(); 
12 
13  StructDescriptor itemDescriptor = 
14   StructDescriptor.createDescriptor("FOO_TYPE",conn); 
15 
16  OracleCallableStatement call = 
17   (OracleCallableStatement) conn.prepareCall("declare\n" 
18    + " x foo_type;\n" 
19    + "begin\n" 
20    + " x := foo_type(5);\n" 
21    + " x.proc(10);\n" 
22    + " ? := x;\n" 
23    + "end;\n"); 
24 
25  call.registerOutParameter(1, OracleTypes.STRUCT, "FOO_TYPE"); 
26 
27  call.execute(); 
28 
29  STRUCT myObj = call.getSTRUCT(1); 
30 
31  Datum[] myData = myObj.getOracleAttributes(); 
32 
33  return myData[0].intValue(); 
34 
35  } 
36 } 
37/

Jest to klasa test pokazują, jak można zastosować metodę registerOutParameter na obiekcie SQL, nazwijmy go:

SQL> CREATE OR REPLACE 
    2 FUNCTION show_TestOutParam RETURN NUMBER 
    3 AS LANGUAGE JAVA 
    4 NAME 'TestOutParam.get() return java.lang.int'; 
    5/

Function created 

SQL> select show_testoutparam from dual; 

SHOW_TESTOUTPARAM 
----------------- 
       20 
+1

Duh. Nie myślałem o przekazywaniu PL/SQL do bazy danych, zamiast składni Escape JDBC ... Czy masz jakieś pomysły na temat tego, w jaki sposób 'x' może zostać zwrócony z bloku PL/SQL? W tym przykładzie 'x' nie jest modyfikowane przez procedury/funkcje. Ale może tak być. Więc podczas wywoływania 'x.func (2)' chciałbym mieć zarówno wynik funkcji jak w twoim przykładzie * i * zaktualizowaną wartość 'x', jako' java.sql.SQLData' ... –

+1

Możesz pobierać obiekty SQL z PL/SQL bezpośrednio do java STRUCT (przykład [tutaj] (http://stackoverflow.com/questions/3626061/how-to-call-oracle-stored-procedure-which-include-user-defined- type -in-java)) Jednak zawsze uważam, że jest nieco zawiłe: zobacz moją zaktualizowaną odpowiedź. –

+1

Awesome! Tak, chcę to zrobić. Będzie to używane głównie w mojej [bibliotece abstrakcji baz danych] (http://www.jooq.org). Mogłeś to zobaczyć, ponieważ odpowiedziałeś na moje pytania przed :-). Celem będzie stworzenie mapowania między klasami UDT i Java. To już istnieje, ale tylko dla danych, które może zawierać UDT. Generowanie kodu źródłowego Javy dla funkcji i procedur członków jest jeszcze bardziej interesujące, ponieważ dzięki temu interakcje między językiem Java i językiem PL/SQL są bardzo łatwe w obsłudze kodu klienta, ponieważ nie muszą one nękać tego rodzaju sztuczek JDBC. Bardzo dziękuję za Twoją pomoc. –

Powiązane problemy