В Oracle Apex мне нужно отображать записи пользователю из источника представления. Затем пользователь установит флажок, соответствующий записям, которые он хочет обработать, а затем нажмет кнопку, чтобы отправить страницу. Пользовательский процесс будет проходить по выбранным записям и обрабатывать их.
К моему удивлению, это непростая задача в Apex. В классических отчетах я обнаружил, что для этого можно использовать массивы APEX_APPLICATION.Gxxx.
FOR i IN 1.. APEX_APPLICATION.G_F01.COUNT LOOP
p_my_custom_dml(....);
END LOOP;
Но нет простого способа получить доступ к данным, соответствующим строке текущего флажка. Мне нужно было бы засунуть все мои другие столбцы в их собственный массив, а затем иметь второй цикл, который сопоставляет их по первичному ключу.
Интерактивные сетки имеют «селектор строк», который на первый взгляд кажется идеальным. Но селектор строк не «загрязняет» записи, поэтому вы вынуждены писать JS для циклического просмотра выбранных строк и обновления некоторого скрытого поля, чтобы загрязнить их.
Новый метод, который я изучаю, — это использование коллекций. Я почерпнул идею из этого поста. Я хотел бы создать коллекцию в APEX, а затем просмотреть эту же коллекцию непосредственно в моей базе данных Oracle. Поскольку коллекции основаны на сеансе, мне нужно будет передать идентификатор сеанса из APEX в мою процедуру оракула. Что-то вроде...
CREATE OR replace PROCEDURE my_custom_proc ( p_session IN NUMBER DEFAULT wwv_flow.g_instance,
p_app IN VARCHAR DEFAULT apex_application.g_flow_id,
p_ws_id IN VARCHAR DEFAULT apex_workspaces.workspace_id)
IS
CURSOR c1 IS
SELECT *
FROM apex_collections
WHERE collection_name = 'MY_COLLECTION';
BEGIN
-- Set Workspace ID
wwv_flow_api.Set_security_group_id (p_ws_id);
-- Set Application ID
apex_application.g_flow_id := p_app;
-- Set Session ID
apex_application.g_instance := p_session;
--loop over collection records
FOR RECORD IN c1
LOOP
--process records;
END LOOP;
END;
Затем я бы назвал эту процедуру из APEX, например...
BEGIN
my_custom_proc(v('APP_SESSION'),
v('APP_ID),
apex_application_install.get_workspace_id);
END;
Мне нравится этот подход, потому что мне не нужно иметь дело с вводом данных строки APEX в мою процедуру. Я могу просто получить доступ ко всему этому непосредственно на стороне базы данных. Но тот факт, что я нигде не видел этого решения, меня беспокоит.
Мой вопрос: есть ли какие-либо проблемы с безопасностью или другие проблемы с этим методом, которых я не вижу? Я читал что-то, что заявленным идентификаторам сеанса нельзя доверять, поскольку они могут измениться, но я не уверен, что мне нужно беспокоиться об этом.
Процессу страницы не нужно беспокоиться об идентификаторе сеанса, как вы указали выше.
Сообщение в блоге, на которое вы ссылаетесь, касалось только запроса представления коллекции из SQL Developer. Это удобно для отладки, но чище было бы использовать пакет APEX_SESSION.
begin
apex_session.ATTACH (
p_app_id => 123
,p_page_id => 1
,p_session_id => 12111327500847);
end;
/
Вы можете добавить участников в свою коллекцию, используя способ, аналогичный тому, что я описал здесь, и просто запросите таблицу apex_collections с соответствующим именем collection_name в процессе своей страницы.
Чтобы было ясно, использование APEX_SESSION предназначено для целей отладки только в отдельном сеансе в таком инструменте, как SQL Developer. Для вашего приложения нет необходимости явно ссылаться на идентификатор сеанса при запросе представления APEX_COLLECTIONS.
Спасибо за ваше решение, Скотт. Чтобы вызвать apex_session.ATTACH с динамическими аргументами из процедуры базы данных Oracle, мне нужно будет передать session/page/app_id в процедуру, используя тот же метод, который я использовал в моем my_custom_proc (v('APP_SESSION') и т. д.. )