Наконец-то разобрался как вызывать хранимые 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:
2

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) Генерируем класс для объекта сущности:

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) Генерируем классы для объекта представления и строки представления:

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:

8

9) С моделью на этом все. Нажимаем Save All и Rebuid All и переходим к интерфейсу

10) Для управления я взял основную страницу приложения (в моем примере DeptEmpPage.jsf). В AppModuleDataControl присутствует наш метод:

11

11) Из палитры компонентов бросаем на страницу кнопку (Button):

11_

12) У отмеченной кнопки нажимаем на выпадающее меню (Button Actions, справа от кнопки) и выбираем Bind to ADF Control в котором выбираем наш метод:

12

После этого откроется окно Edit Action Binding:

12-2

В этом окне, в параметрах, в колонке Value, нужно открыть выпадающий список и выбрать Show El Expression Builder. В открывшемся окне выбрать источник откуда параметр получит строку (в моем примере текущая строка):
12-3

Нажимаем OK везде, где оно есть

13) В свойствах кнопки, в поле Text переименовываем ее в что-либо более человечное Подмигивающая рожица

14) Из Data Control кидаем возвращаемое значение метода на страницу и выбираем Text –> ADF Output Text w/ Label (можем сразу и изменить label):
14

15) Теперь создадим Partial trigger, чтобы после вызова функции, в компоненте Output Text отобразилось возвращаемое значение. Для этого в свойствах текста (Output Text), в разделе Behavior, нажимаем правую кнопку на свойстве Partial Triggers и выбираем Edit. В открывшемся окне переносим, созданную ранее кнопку в Selected:
15
Нажимаем OK

16) Сохраняем и запускаем наше приложение. После запуска нажимаем кнопку и наслаждаемся результатом:
16

Ссылки:
Мой готовый пример
руководство Developing Rich Web Applications With Oracle ADF
раздел документации Developing Fusion Web Applications with Oracle Application Development Framework – 16 Extending Business Components Functionality

2 comments

  1. Что делать, если при вызове процедуры возникает ошибка:
    “Невозможно создать тип объекта домена java.lang.Number: класс является классом интерфейса или абстрактным классом, поэтому создать экземпляры его объектов невозможно.”?

    1. Не совсем понятен контекст, но очевидно, что т.к. Number в java – действительно абстрактный класс, то надо использовать созданные на его основе примитивы float или int или другой подходящий. Подробности тут. При вызове процедуры – это скорее всего проблема биндинга параметров.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: