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