Источники данных обеспечивают работу связанных с данными (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
дескриптора экрана.