Справочник по YAML
Динамическая модель сериализуется в YAML под корневым ключом model:. На этой странице полностью документируется схема: каждое поле, его тип, является ли оно обязательным, его значение по умолчанию и правила, которые им управляют. Руководство, ориентированное на задачи, см. в разделах Определение модели и Экраны и пункты меню.
Модель
Корень model содержит следующие поля верхнего уровня:
| Поле | Тип | Обязательно | Примечания |
|---|---|---|---|
|
string |
нет |
Java-пакет для сгенерированных классов динамических сущностей, перечислений и экранов. Если опущено или пусто, эффективным значением является базовый пакет последнего модуля Jmix плюс |
|
list |
нет |
Определения динамических перечислений. Отсутствие или |
|
list |
нет |
Расширения статических сущностей и определения динамических сущностей. Отсутствие или |
Имена и разрешение
Определения сущностей сопоставляются по имени сущности Jmix:
-
Если сущность с именем
nameуже существует в метаданных, определение расширяет эту статическую сущность динамическими атрибутами, валидацией, уникальностью или переопределениями экранов. -
Если сущность с таким именем в метаданных отсутствует, Динамическая модель создаёт динамическую сущность с тем же именем сущности Jmix и сгенерированным Java-классом с именем
<effective basePackage>.<name>.
Используйте Java-подобные имена для динамических сущностей, атрибутов, классов перечислений и значений перечислений. Сгенерированные идентификаторы базы данных нормализуются автоматически:
-
camel case разбивается на имена с подчёркиваниями в верхнем регистре, например
loyaltyLevelстановитсяLOYALTY_LEVEL; -
неподдерживаемые символы заменяются подчёркиваниями;
-
зарезервированные слова получают завершающее подчёркивание, например
userстановитсяUSER_; -
идентификаторы, превышающие ограничение СУБД, сокращаются с помощью 8-символьного хеша.
Значения локализации
Большинство подписей используют простую карту «локаль-сообщение»:
messages:
en: "Loyalty level"
de: "Treuestufe"
Некоторые поля являются локализованными значениями и принимают либо простую строку:
viewTitle: "Benefit"
либо словарь локалей:
viewTitle:
en: "Loyalty levels"
de: "Treuestufen"
Ключи локалей должны быть непустыми и отображаться в строки. Во время выполнения предпочтение отдаётся точной локали, затем локали только с языком, затем первому значению словаря.
Перечисления
Динамические перечисления объявляются в model.enumerations:
enumerations:
- name: "CustomerGrade"
messages:
en: "Customer grade"
values:
- name: "PLATINUM"
id: "30"
messages:
en: "Platinum"
- name: "GOLD"
id: "20"
messages:
en: "Gold"
- name: "BRONZE"
id: "10"
messages:
en: "Bronze"
Поля перечисления:
| Поле | Тип | Обязательно | Примечания |
|---|---|---|---|
|
string |
да |
Короткое имя класса или полностью квалифицированное имя класса. Короткие имена разрешаются относительно |
|
list |
да |
Должно содержать хотя бы одно значение. |
|
map |
нет |
Подписи для класса перечисления. |
Поля значения перечисления:
| Поле | Тип | Обязательно | Примечания |
|---|---|---|---|
|
string |
да |
Имя Java-константы перечисления. |
|
string |
да |
Хранимый ID перечисления. Все ID в одном динамическом перечислении должны быть однородными: либо все парсятся как 32-битные целые числа, либо все являются нецелочисленными строками. |
|
map |
нет |
Подписи для этого значения перечисления. |
Динамические перечисления реализуют EnumClass<Integer>, когда все ID являются целочисленными строками, в противном случае — EnumClass<String>.
Ссылки атрибутов на перечисления используют поле enumeration:
- name: "grade"
enumeration: "CustomerGrade" # short name, resolved via base package
messages:
en: "Grade"
Статические перечисления также поддерживаются, если класс реализует EnumClass. Используйте полностью квалифицированное имя класса или короткое имя, когда класс перечисления находится в basePackage. Сопоставление перечислений с БД поддерживает как целочисленные ID, так и строковые ID.
Сущности
Определения сущностей объявляются в model.entities:
- name: "Benefit"
messages:
en: "Benefit"
attributes:
- name: "name"
javaClass: "java.lang.String"
instanceName: true
messages:
en: "Name"
views:
- type: "detail"
viewId: "Benefit.detail"
viewTitle: "Benefit"
descriptor:
template: "default"
| Поле | Тип | Обязательно | Примечания |
|---|---|---|---|
|
string |
да |
Имя сущности Jmix. Существующее имя в метаданных означает расширение статической сущности; в противном случае создаётся динамическая сущность. |
|
string |
нет |
Физическое JPA-хранилище для динамических сущностей. Пустое значение и |
|
list |
нет |
Динамические атрибуты. Отсутствие или |
|
list |
нет |
Именованные ограничения уникальности на уровне сущности. |
|
list |
нет |
Экраны UI, принадлежащие сущности. |
|
object |
нет |
CRUD-разрешения ролей для сущности. Поддерживается только для динамических сущностей. |
|
object |
нет |
Ограничения валидации на уровне сущности. |
|
map |
нет |
Подписи сущности. |
Таблицы динамических сущностей используют настраиваемый префикс jmix.dynmodel.dynamic-entity-table-prefix, по умолчанию DYN_. Динамические атрибуты статических сущностей хранятся в дополнительных таблицах с использованием jmix.dynmodel.static-entity-table-prefix, по умолчанию DYN_. Дополнительные таблицы статических сущностей создаются в том же физическом хранилище, что и владеющая ими статическая сущность.
Атрибуты
Каждый атрибут должен определять ровно один вид:
-
тип данных:
javaClass; -
ссылка:
entityName; -
перечисление:
enumeration.
- name: "Customer"
attributes:
- name: "taxId"
javaClass: "java.lang.String"
length: 20
required: true
unique: true
validation:
constraints:
- annotation: "Pattern"
parameters:
regexp: "^[A-Z0-9-]+$"
message:
en: "Tax ID can contain uppercase letters, digits and dashes only"
messages:
en: "Tax ID"
| Поле | Тип | Обязательно | Примечания |
|---|---|---|---|
|
string |
да |
Имя атрибута. |
|
string |
вид |
Java-класс для атрибутов типа данных. См. поддерживаемые значения ниже. |
|
string |
вид |
Имя целевой сущности Jmix для ссылок и коллекций. |
|
string |
вид |
Имя динамического или статического перечисления. Короткие имена разрешаются через |
|
integer |
нет |
Длина для строк, значений URI, массивов байтов и перечислений со строковыми ID. |
|
boolean |
нет |
Индикатор LOB. Поддерживается только для атрибутов |
|
boolean |
нет |
Добавляет метаданные обязательности и правило валидации |
|
boolean |
нет |
Сокращённая запись для ограничения уникальности по одному атрибуту с именем |
|
boolean |
нет |
Помечает атрибут как свойство имени экземпляра. Если помечено несколько атрибутов, используется первый, а последующие игнорируются с предупреждением. |
|
boolean |
нет |
Делает ссылку |
|
object |
нет |
Делает атрибут доступным только для чтения и нехранимым. |
|
object |
нет |
Ограничения на уровне атрибута. Не разрешены для вычисляемых атрибутов. |
|
object |
нет |
Разрешения view/modify для атрибута. |
|
map |
нет |
Подписи атрибута. |
Поддерживаемые значения javaClass
Атрибуты типа данных, хранимые в БД, сопоставляются с SQL-типами фреймворком. Используйте эти значения при написании YAML вручную:
| Значение YAML | Тип Java | Сопоставление SQL по умолчанию |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UUID-тип, специфичный для БД |
Примечания:
-
Сериализатор хранит значения
Class#getName()Java. Для массива байтов это[B; скопируйте сериализованное значение, если не уверены. -
Другие Java-классы не поддерживаются хранилищем Динамической модели, если не расширено сопоставление типов БД.
Отклонения, специфичные для БД:
| Тип | HSQLDB / H2 | PostgreSQL | MySQL / MariaDB | SQL Server | Oracle |
|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ссылки
Одиночные ссылки используют entityName:
- name: "loyaltyLevel"
entityName: "LoyaltyLevel"
messages:
en: "Loyalty level"
Правила:
-
Цель должна разрешаться в динамическую сущность, объявленную в модели, или в существующую статическую сущность.
-
Динамические ссылки хранят значение первичного ключа цели.
-
Статические цели с составными первичными ключами не поддерживаются.
-
Владелец и цель должны находиться в одном физическом хранилище.
Коллекции
Атрибуты-коллекции являются упорядоченными списками композиции:
- name: "benefits"
entityName: "Benefit"
collection: true
messages:
en: "Benefits"
Правила:
-
entityNameобязательно. -
Цель должна быть динамической сущностью.
-
javaClass,enumeration,lobиinstanceNameне поддерживаются. -
Коллекции не могут участвовать в ограничениях уникальности.
-
Владелец и цель должны находиться в одном физическом хранилище.
-
Статические владельцы с составными первичными ключами не поддерживаются.
Динамическая модель создаёт внутренние дочерние свойства для обратной ссылки на владельца и столбца порядка. Они не записываются в YAML.
Вычисляемые атрибуты
Вычисляемые атрибуты — это доступные только для чтения, нехранимые свойства, вычисляемые при обращении:
- name: "publicSummary"
javaClass: "java.lang.String"
calculated:
evaluator: "spel"
expression: "(name ?: '') + ': ' + (description ?: '')"
dependsOn:
- "name"
- "description"
messages:
en: "Public summary"
| Поле | Тип | Обязательно | Примечания |
|---|---|---|---|
|
string |
нет |
Имя вычислителя, возвращаемое методом |
|
string |
да |
Выражение, специфичное для вычислителя. Встроенный вычислитель |
|
list |
нет |
Имена непосредственных свойств для загрузки вместе с вычисляемым атрибутом. Пути с точками отклоняются. Отсутствие или |
Правила:
-
Вычисляемый атрибут должен объявлять ровно один результирующий тип с помощью
javaClassилиenumeration. -
entityName,collection,required,validationи уникальность не поддерживаются. -
lob: trueявляется лишь подсказкой UI-метаданных и всё равно требует, чтобыjavaClassбылjava.lang.Stringилиbyte[]. -
Зависимости должны существовать в той же сущности — либо в текущей модели, либо в существующих метаданных.
-
Циклы между вычисляемыми атрибутами в одной сущности отклоняются.
-
Изменение существующего хранимого атрибута на вычисляемый или существующего вычисляемого атрибута на хранимый не поддерживается. Изменение результирующего типа вычисляемого атрибута также не поддерживается.
Встроенный вычислитель SpEL разрешает чтение свойств с учётом метаданных и зарегистрированные функции DynamicCalculatedAttributeFunction. Он не предоставляет доступ к Spring-бинам, T(…), конструкторам, произвольным вызовам методов, рефлексии, доступу к загрузчику классов или инфраструктурным API.
Валидация атрибута
Валидация атрибута объявляется в attributes[].validation.constraints:
validation:
constraints:
- annotation: "Pattern"
parameters:
regexp: "^[A-Z0-9-]+$"
message:
en: "Tax ID can contain uppercase letters, digits and dashes only"
Поля ограничения:
| Поле | Тип | Обязательно | Примечания |
|---|---|---|---|
|
string |
да |
Псевдоним ограничения. См. поддерживаемые псевдонимы ниже. |
|
map |
нет |
Значения YAML — скаляр/список/объект. Имена параметров зависят от ограничения. Отсутствие становится пустой картой. |
|
list |
нет |
Псевдонимы групп или полностью квалифицированные имена классов групп валидации. Отсутствие означает |
|
локализованное значение |
нет |
Простая строка или карта локалей. |
Поддерживаемые группы:
-
Default; -
UiComponentChecks; -
UiCrossFieldChecks; -
RestApiChecks; -
полностью квалифицированные имена классов, разрешаемые с помощью
Class.forName().
Поддерживаемые ограничения атрибута:
| Псевдоним | Применяется к | Параметры |
|---|---|---|
|
любой атрибут |
нет |
|
строки, коллекции, массивы |
нет |
|
строки |
нет |
|
строки, коллекции, массивы |
|
|
строки |
|
|
числовые |
|
|
числовые |
|
|
числовые |
|
|
числовые |
|
|
числовые |
|
|
числовые |
нет |
|
числовые |
нет |
|
числовые |
нет |
|
числовые |
нет |
|
дата/время |
нет |
|
дата/время |
нет |
|
дата/время |
нет |
|
дата/время |
нет |
|
строки |
|
|
строки |
нет |
|
булевы |
нет |
|
булевы |
нет |
Валидация использует семантику null из Bean Validation: null является корректным, если только правилом не является NotNull, NotEmpty, NotBlank, AssertTrue или AssertFalse.
required: true эквивалентно обязательным UI-метаданным плюс правилу NotNull группы по умолчанию. Метаданные валидации не создают ограничений БД.
Валидация сущности
Валидация на уровне сущности объявляется в entities[].validation.constraints:
validation:
constraints:
- name: "discountDescriptionRequired"
target: "entity"
type: "expression"
evaluator: "spel"
expression: "discount == null || description != null"
attributes:
- "discount"
- "description"
path: "description"
groups:
- "UiCrossFieldChecks"
- "RestApiChecks"
message:
en: "Description is required when discount is specified"
| Поле | Тип | Обязательно | Примечания |
|---|---|---|---|
|
string |
нет |
Имя ограничения для диагностики. |
|
string |
да |
Должно быть |
|
string |
да |
|
|
string |
expression |
Встроенный вычислитель выражений — |
|
string |
expression |
Должно вычисляться в |
|
string |
bean |
Имя, возвращаемое бином |
|
list |
нет |
Имена участвующих атрибутов. Каждое имя должно существовать в модели или метаданных. |
|
string |
нет |
Путь свойства нарушения. Пустое значение означает нарушение на уровне бина. |
|
list |
нет |
Те же псевдонимы групп, что и при валидации атрибута. |
|
локализованное значение |
нет |
Простая строка или карта локалей. |
Ограничения-выражения используют тот же подход с ограниченным доступом к свойствам SpEL, что и вычисляемые атрибуты. Ограничения-бины делегируются бинам DynamicModelConstraintValidator приложения.
Ограничения уникальности
Уникальность по одному атрибуту:
unique: true
Составная уникальность:
uniqueConstraints:
- name: "customerCountryTaxIdUnique"
attributes:
- "countryCode"
- "taxId"
message:
en: "Tax ID must be unique within a country"
| Поле | Тип | Обязательно | Примечания |
|---|---|---|---|
|
string |
да |
Логическое имя ограничения. Должно быть непустым и уникальным в рамках сущности. Физическое имя в БД генерируется из имени таблицы плюс это значение. |
|
list |
да |
Хотя бы один прямой динамический атрибут. Дублирующиеся имена отклоняются. |
|
локализованное значение |
нет |
Сообщение о нарушении. |
Правила:
-
attributes[].unique: trueнормализуется в именованное ограничение на уровне сущности перед сравнением и планированием DDL. -
Участвовать могут только прямые хранимые одиночные динамические атрибуты.
-
Вычисляемые атрибуты, коллекции и LOB-атрибуты отклоняются.
-
Статические владельцы с мягким удалением не поддерживаются.
-
Применение нового ограничения уникальности завершается неудачей, если существующие строки уже содержат дубликаты.
-
Уникальность для nullable-значений следует поведению целевой СУБД.
Ресурсные роли
Объявления динамических resourceRoles создают аддитивные политики ресурсов во время выполнения. Опущенные объявления не предоставляют доступ. Роли, перечисленные в jmix.dynmodel.security.full-access-roles, предоставляют полный доступ ко всем ресурсам динамической модели; по умолчанию это system-full-access.
Коды ролей должны быть непустыми. Отсутствующие коды ролей логируются и не предоставляют доступ.
CRUD-разрешения на уровне сущности поддерживаются только для динамических сущностей:
resourceRoles:
read:
- "employee"
- "manager"
create:
- "manager"
update:
- "manager"
delete:
- "manager"
Разрешения атрибутов поддерживаются для динамических атрибутов как статических, так и динамических сущностей:
- name: "countryCode"
javaClass: "java.lang.String"
length: 2
resourceRoles:
view:
- "employee"
- "manager"
modify:
- "manager"
messages:
en: "Country code"
Разрешения для экранов и меню являются списками:
views:
- type: "list"
viewId: "LoyaltyLevel.list"
viewRoute: "loyalty-levels"
viewTitle:
en: "Loyalty levels"
de: "Treuestufen"
templateParams:
includeProperties: ["name", "discount"]
excludeProperties: ["publicSummary"]
resourceRoles:
- "employee"
- "manager"
menuItem:
parentMenu: "application"
insertBefore: "Customer.list"
title:
en: "Loyalty levels"
resourceRoles:
- "employee"
- "manager"
descriptor:
template: "default"
Экраны
Экраны объявляются в entities[].views.
views:
- type: "list"
viewId: "LoyaltyLevel.list"
viewRoute: "loyalty-levels"
viewTitle:
en: "Loyalty levels"
de: "Treuestufen"
templateParams:
includeProperties: ["name", "discount"]
excludeProperties: ["publicSummary"]
resourceRoles:
- "employee"
- "manager"
menuItem:
parentMenu: "application"
insertBefore: "Customer.list"
title:
en: "Loyalty levels"
resourceRoles:
- "employee"
- "manager"
descriptor:
template: "default"
Поля экрана:
| Поле | Тип | Обязательно | Примечания |
|---|---|---|---|
|
string |
динамические сущности |
|
|
string |
да |
Уникальный ID экрана. Объявления динамических и статических экранов должны задавать его явно. |
|
string |
нет |
Сегмент маршрута динамической сущности. По умолчанию слаг, созданный из |
|
локализованное значение |
нет |
Заголовок экрана динамической сущности. Экраны статических сущностей не поддерживают это поле. |
|
map |
нет |
Параметры шаблона динамической сущности. Экраны статических сущностей не поддерживают это поле. |
|
list |
нет |
Коды ролей, которые могут открыть экран. Экраны статических сущностей не поддерживают это поле. |
|
object |
нет |
Пункт меню динамической сущности. Экраны статических сущностей не поддерживают это поле. |
|
object |
статические сущности |
Объявление дескриптора. Экраны динамических сущностей могут опустить его для использования шаблона по умолчанию. Экраны статических сущностей должны предоставлять |
|
string |
нет |
ID компонента выбора экрана списка динамической сущности. По умолчанию |
|
string |
нет |
ID контейнера редактируемой сущности экрана детального просмотра динамической сущности. По умолчанию |
Экраны динамических сущностей
Правила:
-
typeдолжен бытьlistилиdetail. -
viewIdдолжен быть задан явно и должен быть уникальным. -
Если
viewRouteопущено, он генерируется изviewIdпутём приведения к нижнему регистру и замены неалфавитно-цифровых последовательностей на-. -
Маршруты детального просмотра автоматически добавляют
/:id; поэтому самviewRouteне должен заканчиваться на/:id. -
Первый объявленный экран списка становится основным экраном списка для динамической сущности. Первый объявленный экран детального просмотра становится основным экраном детального просмотра.
-
descriptorможет быть опущен, использоватьtemplate: "default", использовать путь к пользовательскому ресурсу-шаблону или предоставлять литеральныйsource. -
Если используется
descriptor.source, он должен быть корректным XML с корнем<view xmlns="http://jmix.io/schema/flowui/view">. -
Явные дескрипторы списка должны содержать ID компонента выбора, по умолчанию
dataGrid. -
Явные дескрипторы детального просмотра должны содержать ID контейнера редактируемой сущности, по умолчанию
entityDc.
Шаблоны по умолчанию:
-
io/jmix/flowui/view/template/list-view.ftlдля экранов списка; -
io/jmix/flowui/view/template/detail-template.ftlдля экранов детального просмотра.
templateParams — это YAML-объект, передаваемый в рендеринг шаблона дескриптора. Динамическая модель не определяет для него фиксированную схему; поддерживаемые ключи зависят от выбранного шаблона. Например, шаблон может потреблять фильтры свойств в виде списка строк:
templateParams:
includeProperties: ["name", "discount"]
excludeProperties: ["publicSummary"]
Переопределения экранов статических сущностей
Объявления экранов статических сущностей переопределяют XML-дескриптор уже зарегистрированного экрана:
- viewId: "Customer.list"
descriptor:
source: |
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<view xmlns="http://jmix.io/schema/flowui/view"
extends="com/company/sample/view/customer/customer-list-view.xml">
<layout>
<dataGrid id="customersDataGrid">
<columns>
<column property="taxId"/>
</columns>
</dataGrid>
</layout>
</view>
Правила:
-
viewIdобязательно и должно ссылаться на зарегистрированный статический экран. -
typeможет быть опущен; он выводится из класса контроллера. -
Поддерживается только
descriptor.source. -
descriptor.template,viewRoute,viewTitle,templateParams,resourceRoles,menuItem,lookupComponentIdиeditedEntityContainerIdотклоняются. -
Сгенерированный контроллер является подклассом текущего зарегистрированного контроллера и сохраняет его маршрут.
Дескриптор
descriptor должен содержать ровно одно из:
descriptor:
template: "default"
или:
descriptor:
source: |
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<view xmlns="http://jmix.io/schema/flowui/view"
extends="com/company/sample/view/customer/customer-list-view.xml">
<layout>
<dataGrid id="customersDataGrid">
<columns>
<column property="taxId"/>
</columns>
</dataGrid>
</layout>
</view>
Меню
Поля menuItem:
| Поле | Тип | Обязательно | Примечания |
|---|---|---|---|
|
string |
да |
Существующий или новый ID родительского меню. Если не найден, создаётся корневое меню с этим ID. |
|
string |
нет |
Вставить перед соседним ID меню, если он найден; в противном случае добавить в конец. |
|
локализованное значение |
нет |
По умолчанию используется заголовок экрана, когда опущено. |
|
list |
нет |
Коды ролей, которые могут получить доступ к пункту меню. |
Пункты меню экранов детального просмотра получают параметр маршрута id=new.