Как мы знаем, определение объекта представления поддерживает три режима SQL. Есть нормальный , декларативный и экспертный режимы. В этом посте я собираюсь сосредоточиться на декларативном режиме SQL. Этот интеллектуальный режим позволяет платформе автоматически создавать запросы SQL во время выполнения в соответствии с атрибутами, запрашиваемыми уровнем представления. Кроме того, в зависимости от запрашиваемых атрибутов фреймворки строят не только предложение Select но весь запрос. Таким образом, предложение From содержит только объекты, которые необходимы для предоставления запрашиваемых атрибутов, и в результате выполнения VO только эти объекты создаются и сохраняются в кэше объектов. Декларативный режим SQL широко рекомендуется, и он стал режимом по умолчанию в JDeveloper 12c. Тем не менее, мы должны быть осторожны с этим подходом, поскольку мы можем столкнуться с небольшой ловушкой, которую я собираюсь выделить в этом посте.
В моем примере есть простой VO, основанный на сущностях сотрудников и отделов:
 
  VO настроен на использование декларативного режима SQL. 
В проекте ViewController есть пара страниц, содержащих таблицу с сотрудниками (Main) и форму с данными о сотрудниках (Detail):
 
  Обе страницы используют один и тот же экземпляр VOmployees VO, поэтому, когда мы перейдем из таблицы в форму сведений, мы увидим сведения о выбранном сотруднике.  Это стандартный и очень распространенный подход. 
Итак, давайте немного поиграем с этой средой и рассмотрим три простых варианта использования.
Вариант использования № 1. Таблица содержит все атрибуты, которые имеет форма детализации:
В этом случае все довольно ясно. VO извлекает все обязательные атрибуты с помощью следующего запроса:
| 1 2 3 4 5 6 7 8 | SELECTEmployees.EMPLOYEE_ID,                Employees.FIRST_NAME,                  Employees.LAST_NAME,                Employees.DEPARTMENT_ID,                Departments.DEPARTMENT_NAME,                Departments.DEPARTMENT_ID ASDEPARTMENT_ID1FROMEMPLOYEES Employees, DEPARTMENTS DepartmentsWHEREEmployees.DEPARTMENT_ID = Departments.DEPARTMENT_ID | 
Итак, когда мы переходим из таблицы в детальную форму, все атрибуты текущей строки VO уже заполнены, и ничего лишнего не происходит.
Случай использования № 2. Таблица не содержит DepartmentName, но содержит атрибут DepartmentId1, который является первичным ключом сущности Departments.
В этом случае SQL-запрос выглядит так:
| 1 2 3 4 5 6 7 | SELECTEmployees.EMPLOYEE_ID,                Employees.FIRST_NAME,                  Employees.LAST_NAME,                Employees.DEPARTMENT_ID,                Departments.DEPARTMENT_ID ASDEPARTMENT_ID1FROMEMPLOYEES Employees, DEPARTMENTS DepartmentsWHEREEmployees.DEPARTMENT_ID = Departments.DEPARTMENT_ID | 
Таким образом, DepartmentName не был выбран. Тем не менее, объекты отдела были созданы, и они хранятся в кэше объектов. Но эти объекты имеют только один заполненный атрибут DepartmentId. Остальные атрибуты в этих объектах пусты. Когда мы переходим из таблицы в детальную форму, структура сталкивается с проблемой, поскольку атрибут DepartmentName текущей строки VO не заполняется, и это заставляет экземпляр объекта извлекать себя из базы данных. И экземпляр объекта запускает следующий запрос, чтобы заполнить все атрибуты, которые он имеет:
| 1 2 3 4 5 | SELECTDEPARTMENT_ID,               DEPARTMENT_NAME,               MANAGER_ID,               LOCATION_IDFROMDEPARTMENTS Departments WHEREDEPARTMENT_ID=:ID | 
Случай использования № 3. Таблица содержит только атрибуты сотрудников.
В этом случае ВО выполняет следующий запрос:
| 1 2 3 4 5 | SELECTEmployees.EMPLOYEE_ID,               Employees.FIRST_NAME,                 Employees.LAST_NAME,               Employees.DEPARTMENT_ID FROMEMPLOYEES Employee | 
Таким образом, в предложении from нет отделов, и в результате выполнения VO не создаются никакие сущности отделов. Когда мы переходим к подробному виду, каркас просто не может заставить экземпляр объекта извлечь DepartmentName из базы данных. Потому что этот экземпляр не существует.
Таким образом, форма сведений содержит пустой атрибут DepartmentName. Кроме того, в 12c мы получим исключение в таком случае:
На самом деле это та ловушка, о которой я упоминал в самом начале этого поста. Чтобы устранить проблему в этом случае использования, мы можем добавить атрибут DepartmentId1 в определение привязки дерева таблицы:
| 01 02 03 04 05 06 07 08 09 10 11 12 13 | <tree IterBinding="VEmployeesIterator"id="VEmployees">  <nodeDefinition       DefName="com.adfpractice.blog.declarativemodeexample.model.VEmployees"       Name="VEmployees0">    <AttrNames>      <Item Value="EmployeeId"/>      <Item Value="FirstName"/>      <Item Value="LastName"/>      <Item Value="DepartmentId"/>      <Item Value="DepartmentId1"/>    </AttrNames>  </nodeDefinition></tree> | 
Это даст каркас для выполнения запроса, как в сценарии использования № 2.
Второй вариант — установить «Выбрано в запросе» для атрибута DepartmentId1 в определении VO. Это заставит платформу всегда включать атрибут в предложении Select и всегда включать объект Departments в предложении From .
Это оно!
| Ссылка: | Декларативный SQL Mode Pitfall от нашего партнера по JCG Евгения Федоренко в блоге ADF Practice . | 






