TAk. LOB jest wskaźnikiem/odniesieniem do pamięci/dysku. Musisz najpierw "memalloc()" (... zainicjować) pamięć, przypisać wskaźnik/odwołanie do zmiennej LOB. To właśnie dbms_lob.createTemporary()
jest dla. O ile nie zainicjujesz zmiennej LOB z prawidłowym lokalizatorem LOB, wszystkie operacje na tej zmiennej LOB zakończą się niepowodzeniem z ORA-22275: invalid LOB locator specified
.
Ulepszenie: Zrefaktoruj nieco swoją funkcję PL/SQL:(proszę zauważyć, że użyłem fikcyjnego zapytania dla last_60_cpu_cursor
kursor. Nie używaj ponownie kursora, użyj własnego! :-))
create or replace
function statistics_function
( namein in varchar2 )
return clob
is
line clob;
cursor last_60_cpu_cursor is
select 1 as last_60_cpu, sysdate as last_60_event_date
from dual
;
begin
dbms_lob.createtemporary(lob_loc => line, cache => true, dur => dbms_lob.call);
for cv in last_60_cpu_cursor loop
dbms_lob.append(line, to_char(cv.last_60_event_date)||'i'||to_char(cv.last_60_cpu)||chr(10));
end loop;
dbms_lob.append(line, 'last_60_cpu'||chr(10));
return line;
end statistics_function;
- Nie musisz otwierać+pobierać+zamykać kursora. Zwykła pętla kursora wystarczy (jeśli nie lepiej, dzięki niejawnemu pobieraniu zbiorczemu pod maskami).
- Jawnie zadeklaruj tymczasowy obiekt LOB jako buforowany (
cache => true
; jak już masz). Zapewnia to dodawanie porcji danych do LOB w pamięci, zamiast na dysku (cache => false
). - Połącz ciągi, które mają być dołączone do LOB, aby zminimalizować liczbę wywołań
dbms_lob.append()
. - Usuń
dbms_output.put_line()
z twojej funkcji. W przypadku zawartości LOB większej niż 32 KB i tak spowoduje to zgłoszenie wyjątku.
Ponadto, gdy zakończysz dostarczanie LOB z powrotem do środowiska Java, uwolnij tymczasowy LOB . (Nie jestem facetem od Javy, nie mogę sam napisać fragmentu kodu Java.)
Ponadto masz błąd koncepcyjny w kodzie Java; rejestracja zwrotu funkcji jako Types.VARCHAR
jest źle. Powinieneś raczej użyć dedykowanego typu CLOB Oracle
. (Widziałem je w C#, Java też musi je mieć.)
Ponadto istnieje jeden problem z wydajnością Twojego rozwiązania. Twoja funkcja zwraca LOB. W PL/SQL każda wartość funkcji jest zwracana do jej wywołującego jako głęboka kopia wartości wewnętrznej. W związku z tym, jeśli zwracasz LOB z funkcji, zawartość LOB jest duplikowana w tle z nowym lokalizatorem LOB (/pointer/reference). Powinieneś użyć Możesz rozważyć użycie procedury składowanej zamiast funkcji i przekazać LOB do Javy jako out nocopy
parametr. Zapisany proces wyglądałby wtedy tak:
create or replace
procedure statistics_function
( namein in varchar2
, lob_out out nocopy clob )
is
cursor last_60_cpu_cursor is
select 1 as last_60_cpu, sysdate as last_60_event_date
from dual
;
begin
dbms_lob.createtemporary(lob_loc => lob_out, cache => true, dur => dbms_lob.session);
for cv in last_60_cpu_cursor loop
dbms_lob.append(lob_out, to_char(cv.last_60_event_date)||'i'||to_char(cv.last_60_cpu)||chr(10));
end loop;
dbms_lob.append(lob_out, 'last_60_cpu'||chr(10)||chr(10));
end statistics_function;
Jak będzie wyglądać Twoje wywołanie Java, zależy od Ciebie i Dokument JDBC ; ale na pewno LOB zwrócony w ten sposób oznaczałby brak kopiowania zawartości w tle. Oczywiście nadal obowiązuje potrzeba zwolnienia przydzielonego tymczasowego LOB.