Как мы знаем, определение объекта представления поддерживает три режима 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
|
SELECT Employees.EMPLOYEE_ID, Employees.FIRST_NAME, Employees.LAST_NAME, Employees.DEPARTMENT_ID, Departments.DEPARTMENT_NAME, Departments.DEPARTMENT_ID AS DEPARTMENT_ID1FROM EMPLOYEES Employees, DEPARTMENTS DepartmentsWHERE Employees.DEPARTMENT_ID = Departments.DEPARTMENT_ID |
Итак, когда мы переходим из таблицы в детальную форму, все атрибуты текущей строки VO уже заполнены, и ничего лишнего не происходит.
Случай использования № 2. Таблица не содержит DepartmentName, но содержит атрибут DepartmentId1, который является первичным ключом сущности Departments.
В этом случае SQL-запрос выглядит так:
|
1
2
3
4
5
6
7
|
SELECT Employees.EMPLOYEE_ID, Employees.FIRST_NAME, Employees.LAST_NAME, Employees.DEPARTMENT_ID, Departments.DEPARTMENT_ID AS DEPARTMENT_ID1FROM EMPLOYEES Employees, DEPARTMENTS DepartmentsWHERE Employees.DEPARTMENT_ID = Departments.DEPARTMENT_ID |
Таким образом, DepartmentName не был выбран. Тем не менее, объекты отдела были созданы, и они хранятся в кэше объектов. Но эти объекты имеют только один заполненный атрибут DepartmentId. Остальные атрибуты в этих объектах пусты. Когда мы переходим из таблицы в детальную форму, структура сталкивается с проблемой, поскольку атрибут DepartmentName текущей строки VO не заполняется, и это заставляет экземпляр объекта извлекать себя из базы данных. И экземпляр объекта запускает следующий запрос, чтобы заполнить все атрибуты, которые он имеет:
|
1
2
3
4
5
|
SELECT DEPARTMENT_ID, DEPARTMENT_NAME, MANAGER_ID, LOCATION_IDFROM DEPARTMENTS Departments WHERE DEPARTMENT_ID=:ID |
Случай использования № 3. Таблица содержит только атрибуты сотрудников.
В этом случае ВО выполняет следующий запрос:
|
1
2
3
4
5
|
SELECT Employees.EMPLOYEE_ID, Employees.FIRST_NAME, Employees.LAST_NAME, Employees.DEPARTMENT_ID FROM EMPLOYEES 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 . |






