Наконец-то разобрался как вызывать хранимые PL/SQL процедуры/функции из ADF, и для тех кто тоже хочет разобраться, но еще этого не сделал (а также для себя, чтобы не забыть), я написал это пошаговое руководство. За основу приложения взят пример из учебника “Developing Rich Web Applications With Oracle ADF” для стандартной демо-схемы БД Oracle HR.
1) В БД добавляем простую функцию (я решил подсчитать сумму зарплаты по департаменту):
create or replace function get_sum_salary_by_dept ( p_dept_id in number ) return number as v_result number; begin select sum(salary) into v_result from employees where department_id = p_dept_id; return v_result; end get_sum_salary_by_dept;
2) Создаем имплементацию Application Module:
3) В получившийся java-класс добавляем общий метод (для удобства я его сделал статическим) запуска хранимых функций:
// Some constants public static int NUMBER = Types.NUMERIC; public static int DATE = Types.DATE; public static int VARCHAR2 = Types.VARCHAR; //Делаем метод статическим и добавляем передачу в него транзакции /* В import надо добавить import java.sql.CallableStatement; import java.sql.SQLException; import java.sql.Types; import oracle.jbo.JboException; import oracle.jbo.server.DBTransaction; */ public static Object callStoredFunction(DBTransaction tr, int sqlReturnType, String stmt, Object[] bindVars) { CallableStatement st = null; try { // 1. Create a JDBC CallabledStatement st = tr.createCallableStatement( "begin ? := "+stmt+";end;",0); // 2. Register the first bind variable for the return value st.registerOutParameter(1, sqlReturnType); if (bindVars != null) { // 3. Loop over values for the bind variables passed in, if any for (int z = 0; z < bindVars.length; z++) { // 4. Set the value of user-supplied bind vars in the stmt st.setObject(z + 2, bindVars[z]); } } // 5. Set the value of user-supplied bind vars in the stmt st.executeUpdate(); // 6. Return the value of the first bind variable return st.getObject(1); } catch (SQLException e) { throw new JboException(e); } finally { if (st != null) { try { // 7. Close the statement st.close(); } catch (SQLException e) { throw new JboException(e); } } } }
4) Генерируем класс для объекта сущности:
5) В получившийся класс добавляем метод:
public Number callGetSumSalaryByDept() {
Number n = this.getDepartmentId();
return (Number)AppModuleImpl.callStoredFunction(getDBTransaction(),
AppModuleImpl.NUMBER, “get_sum_salary_by_dept(?)”, new Object[]{n});
}
6) Генерируем классы для объекта представления и строки представления:
7) В класс объекта представления (в моем примере DepartmentsViewImpl.java) добавляем метод, вызывающий метод класса сущности:
public Float getDepartmentSalarySum(Row row){ DepartmentsViewRowImpl currentRow = (DepartmentsViewRowImpl)row; DepartmentsImpl departmentEntity = currentRow.getDepartments(); Float res = departmentEntity.callGetSumSalaryByDept().floatValue(); return res; }
8) В свойствах представления, на вкладке Java, в разделе Client Interface, кликаем кнопку редактирования и, в открывшемся окне, переносим наш метод в Selected:
9) С моделью на этом все. Нажимаем Save All и Rebuid All и переходим к интерфейсу
10) Для управления я взял основную страницу приложения (в моем примере DeptEmpPage.jsf). В AppModuleDataControl присутствует наш метод:
11) Из палитры компонентов бросаем на страницу кнопку (Button):
12) У отмеченной кнопки нажимаем на выпадающее меню (Button Actions, справа от кнопки) и выбираем Bind to ADF Control в котором выбираем наш метод:
После этого откроется окно Edit Action Binding:
В этом окне, в параметрах, в колонке Value, нужно открыть выпадающий список и выбрать Show El Expression Builder. В открывшемся окне выбрать источник откуда параметр получит строку (в моем примере текущая строка):
Нажимаем OK везде, где оно есть
13) В свойствах кнопки, в поле Text переименовываем ее в что-либо более человечное
14) Из Data Control кидаем возвращаемое значение метода на страницу и выбираем Text –> ADF Output Text w/ Label (можем сразу и изменить label):
15) Теперь создадим Partial trigger, чтобы после вызова функции, в компоненте Output Text отобразилось возвращаемое значение. Для этого в свойствах текста (Output Text), в разделе Behavior, нажимаем правую кнопку на свойстве Partial Triggers и выбираем Edit. В открывшемся окне переносим, созданную ранее кнопку в Selected:
Нажимаем OK
16) Сохраняем и запускаем наше приложение. После запуска нажимаем кнопку и наслаждаемся результатом:
Ссылки:
Мой готовый пример
руководство Developing Rich Web Applications With Oracle ADF
раздел документации Developing Fusion Web Applications with Oracle Application Development Framework – 16 Extending Business Components Functionality
Что делать, если при вызове процедуры возникает ошибка:
“Невозможно создать тип объекта домена java.lang.Number: класс является классом интерфейса или абстрактным классом, поэтому создать экземпляры его объектов невозможно.”?
Не совсем понятен контекст, но очевидно, что т.к. Number в java – действительно абстрактный класс, то надо использовать созданные на его основе примитивы float или int или другой подходящий. Подробности тут. При вызове процедуры – это скорее всего проблема биндинга параметров.