Источники данных обеспечивают работу связанных с данными (data-aware) компонентов.
Визуальные компоненты сами не обращаются к Middleware, а получают экземпляры сущностей из связанных источников данных. При этом один источник данных может обслуживать несколько визуальных компонентов, если им нужен один и тот же экземпляр или набор экземпляров.
Связь визуального компонента и источника данных проявляется в следующем:
-
При изменении пользователем значения в компоненте новое значение проставляется в атрибуте сущности, находящейся в источнике.
-
При изменении атрибута сущности из кода новое значение проставляется и отображается в визуальном компоненте.
-
Для слежения за вводом пользователя можно использовать как слушатель источника данных, так и слушатель значения визуального компонента - они срабатывают друг за другом.
-
При необходимости прочитать или записать значение атрибута сущности в коде предпочтительнее использовать источник данных, а не компонент. Рассмотрим пример чтения атрибута:
@Inject private FieldGroup fieldGroup; @Inject private Datasource<Order> orderDs; public void init(Map<String, Object> params) { Customer customer; // Get customer from component customer = (Customer) fieldGroup.getFieldValue("customer"); // Get customer from datasource customer = orderDs.getItem().getCustomer(); }Как видно из примера, работа со значениями атрибутов сущностей через компонент требует приведения типа и, в случае FieldGroup, указания имени атрибута в виде строки. В то же время, получив методом
getItem()из источника данных хранящийся в нем экземпляр, можно напрямую читать и изменять значения его атрибутов.
Как правило, визуальный компонент привязывается к атрибуту, непосредственно принадлежащему сущности, находящейся в источнике
данных. В приведенном выше примере компонент привязан к атрибуту customer сущности Order.
Можно также привязать компонент к атрибуту связанной сущности, например к customer.name. В этом случае компонент будет корректно отображать значение атрибута name, но при его изменении пользователем слушатели источника данных вызваны не будут, и изменения не будут сохранены. Поэтому
привязывать компонент к атрибутам второго и более порядка имеет смысл только для отображения, например в Label, колонке Table или установив для TextField свойство editable = false.
Источники данных также отслеживают изменения содержащихся в них сущностей, и могут отправлять измененные экземпляры обратно на Middleware для сохранения в базе данных.
Рассмотрим основные интерфейсы источников.
-
Datasource− простейший источник данных, предназначенный для работы с одним экземпляром сущности. Экземпляр устанавливается методомsetItem()и доступен черезgetItem().Стандартной реализацией такого источника является класс
DatasourceImpl, который используется, например, как главный источник данных в экранах редактирования сущностей. -
CollectionDatasource− источник данных, предназначенный для работы с коллекцией экземпляров сущности. Коллекция загружается при вызове методаrefresh(), ключи экземпляров доступны через методgetItemIds(). МетодsetItem()устанавливает, аgetItem()возвращает "текущий" экземпляр коллекции, т.е., например, соответствующий выбранной в данный момент строке таблицы.Способ загрузки коллекции сущностей определяется реализацией. Наиболее типичный - загрузка с Middleware через DataManager, при этом для формирования JPQL запроса используются методы
setQuery(),setQueryFilter().Стандартной реализацией такого источника является класс
CollectionDatasourceImpl, который используется в экранах, отображающих списки сущностей.-
GroupDatasource− подвидCollectionDatasource, предназначенный для работы с компонентомGroupTable.Стандартной реализацией является класс
GroupDatasourceImpl. -
HierarchicalDatasource− подвидCollectionDatasource, предназначенный для работы с компонентамиTreeиTreeTable.Стандартной реализацией является класс
HierarchicalDatasourceImpl.
-
-
NestedDatasource- источник данных, предназначенный для работы с экземплярами, загруженными в атрибуте другой сущности. При этом источник, содержащий сущность-хозяина, доступен методомgetMaster(), а мета-свойство, соответствующее атрибуту хозяина, содержащему экземпляры данного источника, доступно через методgetProperty().Например, в источнике
dsOrderустановлен экземпляр сущностиOrder, содержащий ссылку на экземплярCustomer. Тогда для связи экземпляраCustomerс визуальными компонентами достаточно создатьNestedDatasource, у которого хозяином являетсяdsOrder, а мета-свойство указывает на атрибутOrder.customer.-
PropertyDatasource- подвидNestedDatasource, предназначенный для работы с одним экземпляром или коллекцией связанных сущностей, не являющихся встроенными (embedded).Стандартные реализации: для работы с одним экземпляром -
PropertyDatasourceImpl, для работы с коллекцией -CollectionPropertyDatasourceImpl,GroupPropertyDatasourceImpl,HierarchicalPropertyDatasourceImpl. Последние реализуют также интерфейсCollectionDatasource, однако некоторые его нерелевантные методы, связанные с загрузкой, например,setQuery(), выбрасываютUnsupportedOperationException. -
EmbeddedDatasource- подвидNestedDatasource, содержащий экземпляр встроенной сущности.Стандартной реализацией является класс
EmbeddedDatasourceImpl.
-
-
RuntimePropsDatasource− специфический источник, предназначенный для работы с динамическими атрибутами сущностей.
Как правило, источники данных объявляются декларативно в секции dsContext дескриптора экрана.


