Русский English Тэги View Sergey Zolotaryov's profile on LinkedIn Вход
Работа с хранимыми процедурами в Toplink
Постоянная ссылка 02-02-2009 anydoby java

Задача: сделать много всякой лабуды в хранимой процедуре так, чтобы кэш toplink об этом знал и корректно сфлашил все измененные объекты.

Решение напрашивается само собой: вернуть из процедуры таблицу с именами таблиц, которые мы изменили и ID записей из этих таблиц, которые были затронуты. Однако загвоздка в том, что в Oracle вернуть курсор на временную таблицу из процедуры низзя. Есть некое подобие списков, которые в Oracle называются ARRAY и которые, собственно, пришлось использовать. Потрачена была уйма времени и матюков, чтобы все хозяйство заработало: добавления записей в массивы нету - надо было писать функцию добавления и постоянно следить за индексом массива :) потом прыгать с бубном, чтобы массив хорошо вернулся из базы на Toplink, да и с флашем тоже были проблемы. В общем, обо всем по-порядку...

Итак, для того, чтобы добавлять ID и названия таблиц нам понадобится массив:


create or replace
TYPE OIDS AS TABLE OF VARCHAR(255);

OIDS это тип массива, который мы будем возвращать. Для добавления записей в него будем использовать вот такую функцию:


create or replace
FUNCTION APPEND_TO_ARRAY(source in oids, destination in out nocopy oids, i in number) return number as
new_index number := i;
BEGIN
  IF (source is not null and source.COUNT > 0)
  THEN
      destination.EXTEND(source.COUNT);
      FOR ind IN source.FIRST .. source.LAST
      LOOP
        destination(i + ind) := source(ind);
      END LOOP;
      new_index := i + source.LAST;
  END IF;
  return new_index;
END APPEND_TO_ARRAY;

Функция копирует элементы массива source в destination, а i это индекс, указывающий на последний элемент из source.

А вот и сама процедура:


create or replace
procedure myproc(modified_oids OUT NOCOPY oids) is

temp_oids oids;
v_indx number:=0;

// do something

update mytable t 
set t.mycolumn = 'bla-bla-bla'
returning t.ID || '_mypackage.MyEntity' bulk collect into temp_oids; v_indx := APPEND_TO_ARRAY(temp_oids, modified_oids, v_indx);

// this is how every updated looks like

У Oracle есть замечательная фича - можно вернуть из update строки, которые были затронуты, что мы и спользуем для записи ID измененных строк во временную таблицу, после этого мы добавляем все записи из временной таблицы в таблицу типа OIDS. К сожалению, это самый гуманный из известных мне способов обращения в массивами.

И наконец, вызываем процедуру и получаем результаты:


    StoredProcedureCall call = new StoredProcedureCall();
    call.setProcedureName("MYPROC");
    call.addNamedOutputArgument("modified_oids", "modified_oids", Types.ARRAY, "OIDS");

    DatabaseQuery query = new ValueReadQuery();
    query.setCall(call);

    Object result = toplinkSession.executeQuery(query);
    Object[] resultArray = (Object[])((Array)result).getArray();

В ответ из базы мы получаем массив String, с которыми потом и работаем.

Добавить комментарий

Предыдущая статья Программная аутентификация в Tomcat Следующая статья Swing Explorer