Бэнды и наборы данных
Внутренняя структура отчета состоит из бэндов. Бэнд представляет собой раздел отчета, который может появляться в итоговом документе ноль или более раз.
Бэнд заполняется данными, предоставляемыми одним или несколькими наборами данных, связанными с этим бэндом.
В шаблоне отчета бэнды размечены способом, зависящим от формата файла. Определение отчета включает иерархическую структуру бэндов, соответствующую бэндам шаблона.
На рисунке ниже показан пример бэндов, используемых в отчете:
Бэнд Root в определении отчета предопределен, однако он может не использоваться в шаблоне.
| Примеры различных бэндов и наборов данных можно найти в руководстве Report Generation. |
Бэнды
Вкладка Bands
Вкладка Bands редактора отчетов позволяет определить иерархию бэндов и наборы данных для каждого бэнда.
Бэнд отчета имеет следующие параметры:
-
Name — имя бэнда, уникальное в пределах отчета. Должно содержать только латинские буквы, цифры и знаки подчеркивания.
Если имя бэнда начинается с header, его данные не будут выводиться при использовании форматера таблиц. -
Orientation - ориентация бэнда: Horizontal, Vertical или Crosstab.
-
Horizontal бэнды копируются вниз. Они могут содержать подбэнды.
-
Vertical бэнды копируются вправо.
-
Crosstab бэнды копируются вправо и вниз в виде матрицы.
-
-
Parent - родительский бэнд.
-
Multiple Datasets - установите этот флажок, если хотите определить более одного набора данных для бэнда.
-
Dataset type — тип набора данных.
Каждый бэнд включает один или несколько наборов данных. При запуске отчета наборы данных преобразуются в списки строк, где каждая строка содержит карту пар "имя-значение". Бэнд появляется в отчете столько раз, сколько строк в его самом длинном наборе данных.
Поля, определенные в шаблоне отчета, заменяются соответствующими значениями из набора данных при выполнении отчета. При определении наборов данных можно использовать внешние параметры отчета и поля из других бэндов, что позволяет связывать бэнды.
Каждый отчет имеет бэнд Root. В нем можно создавать наборы данных и ссылаться на их поля из других бэндов.
Обратите внимание, что столбец Dataset name, доступный при работе с несколькими наборами данных, предназначен только для удобства пользователя.
Аннотация @BandDef
Аннотация @BandDef позволяет определять бэнды при создании отчета во время разработки. Она имеет следующие атрибуты:
-
name- имя бэнда, уникальное в пределах отчета. Должно содержать только латинские буквы, цифры и знаки подчеркивания. -
parent- имя родительского бэнда. Может быть опущено только для бэндаRoot. -
root- должно быть установлено вtrueтолько для бэндаRoot. По умолчаниюfalse. -
orientation- ориентация бэнда, определяемая перечислениемOrientation:HORIZONTAL,VERTICAL,CROSS. По умолчаниюHORIZONTAL. -
dataSets- наборы данных, определяемые массивом аннотаций@DataSetDef.
Отчет должен включать определение бэнда Root с атрибутами name = "Root" и root = true.
Порядок аннотаций @BandDef в Java-классе определения отчета важен. Он влияет на порядок вывода бэндов на одном уровне иерархии.
|
Наборы данных
Набор данных SQL
SQL набор данных формируется в результате выполнения SQL-запроса. Рекомендуется использовать псевдонимы для полей результата запроса с помощью оператора as. Также рекомендуется заключать псевдонимы в двойные кавычки, чтобы предотвратить возможное преобразование регистра СУБД:
select u.name as "userName", u.login as "userLogin"
from user_ u
В запросе можно использовать входные параметры отчета и поля родительских бэндов. К параметрам следует обращаться по имени, заключенному в ${}, например, ${dateFrom}. К полям родительских бэндов следует обращаться аналогично, добавляя имя бэнда перед именем поля: ${band1.field1}.
Ниже приведен пример SQL-запроса с параметром groupId, полученным из родительского бэнда group, и внешним параметром enabled:
select u.name as "userName", u.login as "userLogin"
from user_ u
where u.group_id = ${group.groupId}
and u.active = ${active}
and u.deleted_date is null
|
В SQL-запросах следует вручную добавлять условия для фильтрации записей, помеченных как удаленные. |
- Объединение нескольких наборов данных
-
Link field используется для объединения данных из нескольких наборов данных внутри одного бэнда. Может использоваться, когда все данные для строки отчета не могут быть получены одним запросом или Groovy-скриптом.
- Выбор хранилища данных
-
По умолчанию запросы выполняются к основной базе данных. Если требуется выполнить запрос к дополнительному хранилищу данных, укажите его имя в поле Data store.
- Предварительная обработка запросов в бэндах
-
Если необходимо динамически модифицировать SQL/JPQL запрос в зависимости от входных параметров отчета или значений параметров из родительского бэнда, можно использовать предварительную обработку SQL. Механизм шаблонов позволяет модифицировать SQL/JPQL запросы с помощью Groovy. Для активации установите флажок Preprocess query as Groovy template под редактором бэнда. Итоговый запрос будет обработан
GStringTemplateEngine, который получит доступ к:-
параметрам отчета: ${<имя_параметра>},
-
значениям из родительских бэндов: ${<имя_бэнда>.<имя_параметра>}.
Рассмотрим пример: в зависимости от того, передан ли параметр отчета
createTs2, нужно выбрать одно из условий запроса:e.create_ts < ${createTs2}илиe.create_ts < current_timestamp.В этом случае запрос должен выглядеть так:
select e.create_ts, e.id, e.vin from ref_car e where e.create_ts >= ${createTs1} and <% out << (createTs2 != null ? 'e.create_ts < ${createTs2}' : 'e.create_ts < current_timestamp')%>Таким образом, если параметр
createTs2не передан, исходный запрос преобразуется в следующий итоговый запрос:select e.create_ts, e.id, e.vin from ref_car e where e.create_ts >= ${createTs1} and e.create_ts < current_timestampЕсли createTs2 передан, для бэнда будет использован следующий итоговый запрос:
select e.create_ts, e.id, e.vin from ref_car e where e.create_ts >= ${createTs1} and e.create_ts < ${createTs2} -
Набор данных JPQL
Набор данных JPQL формируется в результате выполнения JPQL-запроса. Поля результирующего запроса должны иметь псевдонимы, заданные с помощью оператора as. Аналогично SQL-запросу, в JPQL-запросе можно использовать входные параметры отчета и поля родительских бэндов.
Ниже приведен пример JPQL-запроса с параметром groupId, полученным из родительского бэнда group, и внешним параметром enabled:
select u.name as userName, u.login as userLogin
from User u
where u.group.id = ${group.groupId}
and u.active = ${active}
JPQL-запросы автоматически поддерживают мягкое удаление и возвращают только записи, не помеченные как удаленные.
|
При использовании JPQL-запроса в качестве источника данных для отчета обратите внимание, что запрос выполняется напрямую к базе данных и обходит DataManager. Это означает, что обычные проверки безопасности доступа к данным (на уровне строк и ресурсов) не применяются автоматически. Вы должны убедиться, что ваши JPQL-запросы извлекают только те данные, к которым пользователь имеет право доступа. Вы несете ответственность за реализацию необходимых проверок безопасности в ваших запросах. |
Вы также можете использовать Link field для объединения нескольких наборов данных, использовать Data store для запросов к дополнительному хранилищу данных или активировать предварительную обработку запросов, установив флажок Preprocess query as Groovy template под редактором бэнда.
Набор данных Groovy
Набор данных Groovy формируется в результате выполнения Groovy-скрипта. Скрипт возвращает объект типа List<Map<String, Object>>. Каждый элемент этого списка - объект типа Map<String, Object> - соответствует одной записи набора данных.
В скрипт передаются следующие объекты:
-
params- карта внешних параметров отчета. Пример получения значения параметра:def active = params['active'] -
parentBand- родительский бэнд как объект типаio.jmix.reports.yarg.structure.BandData. Этот объект позволяет получить значение поля родительского бэнда путем вызова методаgetParameterValue(), например:def groupId = parentBand.getParameterValue('groupId') -
currentAuthentication- объект типаio.jmix.core.security.CurrentAuthentication, связанный с текущим аутентифицированным пользователем. Например:def user = currentAuthentication.getUser() -
metadata- объект типаio.jmix.core.Metadata, предоставляющий доступ к метаданным приложения. Например:def metaClass = metadata.getClass('User') -
dataManager- объект типаio.jmix.core.DataManager, предоставляющий CRUD-функциональность. Например:def book = dataManager.load(Book.class).id(bookId).fetchPlan("book.edit").one() -
timeSource- объект типаio.jmix.core.TimeSource, используемый для получения текущего времени. Например:def currentDate = timeSource.currentTimestamp() -
applicationContext- объект типаorg.springframework.context.ApplicationContext, предоставляющий доступ к управляемым бинам. Например:def accountService = applicationContext.getBean(AccountService);
Набор данных Entity
Набор данных Entity состоит из одной строки и формируется с использованием атрибутов одного экземпляра JPA-сущности и связанных с ней сущностей.
Источник данных формируется из внешнего параметра типа Entity, который должен быть описан на вкладке Parameters. Значение в поле Entity parameter name должно совпадать с именем параметра.
Шаблон отчета должен содержать поля с именами атрибутов сущности. Имена атрибутов могут использовать имена из существующего фетч-плана (при установке флажка Use existing fetch plan) или могут быть выбраны кнопкой Select entity attributes.
|
Поскольку механизм отчетов всегда перезагружает сущности в наборе данных Entity из базы данных, вы не можете использовать его для DTO-сущностей или экземпляров JPA-сущностей, не сохраненных в базе данных. Вместо этого используйте Набор данных Groovy и обращайтесь к сущности, переданной как параметр, следующим образом:
|
Набор данных List of Entities
Набор данных List of entities формируется с использованием списка экземпляров JPA-сущностей.
Источник данных формируется с использованием внешнего параметра типа List of entities, который должен быть описан на вкладке Parameters. Значение в поле List of entities parameter name должно совпадать с псевдонимом параметра.
Шаблон отчета должен содержать поля с именами атрибутов сущности. Имена атрибутов могут использовать имена из существующего фетч-плана (при установке флажка Use existing fetch plan) или могут быть выбраны кнопкой Select entity attributes.
|
Поскольку механизм отчетов всегда перезагружает сущности в наборе данных List of entities из базы данных, вы не можете использовать его для DTO-сущностей или экземпляров JPA-сущностей, не сохраненных в базе данных. Вместо этого используйте Набор данных Groovy и обращайтесь к списку сущностей, переданному как параметр, следующим образом:
|
Набор данных JSON
Набор данных JSON генерируется из JSON-данных. Эти данные могут быть получены из следующих источников:
-
Groovy-скрипт
Предполагается, что скрипт, предоставленный пользователем, возвращает JSON-данные в виде строки.
Например:
return ''' { "items": [ { "name": "Java Concurrency in practice", "price": 15000 }, { "name": "Clear code", "price": 13000 }, { "name": "Scala in action", "price": 12000 } ] } ''' -
URL
Механизм отчетов выполнит HTTP-запрос GET по указанному URL.
Например:
https://jsonplaceholder.typicode.com/users -
Parameter
Внешний параметр отчета типа String, содержащий JSON-данные, должен быть описан на вкладке Parameters.
Полученное JSON-дерево запрашивается с помощью JsonPath-запроса. Например, можно использовать JsonPath $.store.book[*] для возврата всех книг из следующего JSON-дерева:
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99,
"isbn": "0-553-21311-3"
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
Для получения более подробной информации о выражениях JsonPath смотрите документацию.
|
Поля, выводимые отчетом, которые имеют типы данных Для этого перейдите на вкладку Value formats экрана деталей отчета и откройте диалог форматера. Например, для поля
|
Аннотация @DataSetDef
Аннотация @DataSetDef позволяет определять наборы данных при создании отчета во время разработки. Она имеет следующие атрибуты:
-
name- имя набора данных. Используется в наборах данных типаDELEGATEдля связи определения набора данных с методом, возвращающим делегат.В кросс-табличном бэнде (
@BandDef.orientation = Orientation.CROSS) наборы данных должны иметь следующие имена:-
Заголовки столбцов:
${band_name}_dynamic_header -
Заголовки строк:
${band_name}_master_data -
Основное содержимое:
${band_name}
-
-
type- тип набора данных, определяемый перечислениемDataSetType. Значения этого перечисления соответствуют типам наборов данных во время выполнения, описанным выше.Обычно в отчетах, создаваемых во время разработки, используются наборы данных типа
DELEGATE. В этом случае они связываются по имени с методами, аннотированными аннотацией@DataSetDelegate.
Аннотация @DataSetDelegate
Аннотация @DataSetDelegate позволяет определить метод, который возвращает делегат для выполнения логики набора данных. Она имеет атрибут name, который должен быть равен имени соответствующего набора данных.
Аннотированный метод не должен иметь параметров и должен возвращать функциональный интерфейс ReportDataLoader.