Добрый день!
У меня вопрос, как работает механизм подгрузки элементов в multiSelectComboBox
? Вот у меня есть следующий дескриптор экрана:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<view xmlns="http://jmix.io/schema/flowui/view"
title="msg://trafficListView.title"
focusComponent="trafficsDataGrid">
<data>
<collection id="trafficsDc"
class="ru.ctsg.damdbf.manager.ui.dto.traffic.TrafficUiDto">
<fetchPlan extends="_base"/>
<loader id="trafficsDl" readOnly="true"/>
</collection>
</data>
<facets>
<dataLoadCoordinator auto="true"/>
<urlQueryParameters>
<pagination component="pagination"/>
</urlQueryParameters>
</facets>
<actions>
<action id="selectAction" type="lookup_select"/>
<action id="discardAction" type="lookup_discard"/>
</actions>
<layout>
<details summaryText="msg://ru.ctsg.damdbf.manager.ui.view.traffic/filter" opened="true"
classNames="detailsListView">
<formLayout>
<responsiveSteps>
<responsiveStep minWidth="0em" columns="3"/>
</responsiveSteps>
<multiSelectComboBox id="filterProcessInfoComboBox" property="processInfo"
label="msg://ru.ctsg.damdbf.manager.ui.view.traffic/processInfo"
width="15em" classNames="filterBox">
</multiSelectComboBox>
<multiSelectComboBox id="filterRequestTypeComboBox"
itemsEnum="ru.ctsg.damdbf.manager.core.enums.RequestType"
label="msg://ru.ctsg.damdbf.manager.ui.view.traffic/requestType" width="15em"
classNames="filterBox"/>
<multiSelectComboBox id="filterTablesNameComboBox" property="tablesName"
label="msg://ru.ctsg.damdbf.manager.ui.view.traffic/tablesName" width="15em"
classNames="filterBox">
</multiSelectComboBox>
<multiSelectComboBox id="filterAttributesNameComboBox" property="attributesName"
label="msg://ru.ctsg.damdbf.manager.ui.view.traffic/attributesName" width="15em"
classNames="filterBox">
</multiSelectComboBox>
<dateTimePicker id="filterTimestampRequestDateTimePicker" property="timestampRequest"
label="msg://ru.ctsg.damdbf.manager.ui.view.traffic/timestampRequest"
width="15em" classNames="filterBox"/>
</formLayout>
<hbox classNames="hboxFilterButton">
<button id="refreshFilterBtn" action="trafficsDataGrid.refresh" classNames="refreshFilterBtn"/>
<button id="clearFilterBtn" action="trafficsDataGrid.clear" classNames="clearFilterBtn"/>
</hbox>
</details>
<dataGrid id="trafficsDataGrid"
width="100%"
minHeight="20em"
dataContainer="trafficsDc"
columnReorderingAllowed="true">
<actions>
<action id="refresh" type="list_refresh" text="msg://ru.ctsg.damdbf.manager.ui.action/Search"
icon="SEARCH"/>
<action id="clear" text="msg://ru.ctsg.damdbf.manager.ui.action/Clear" icon="MINUS_CIRCLE_O"/>
</actions>
<columns resizable="true">
<column key="icon" sortable="false" flexGrow="0" resizable="false"/>
<column property="processInfo"/>
<column property="agentId"/>
<column property="requestType"/>
<column property="tablesName"/>
<column property="attributesName"/>
<column property="trafficRequest"/>
<column property="timestampRequest"/>
<column key="contextMenu" width="10em" flexGrow="0" sortable="false"/>
</columns>
</dataGrid>
<hbox alignSelf="CENTER">
<simplePagination id="pagination" dataLoader="trafficsDl" itemsPerPageVisible="true"
itemsPerPageItems="10, 20, 50, 100" itemsPerPageDefaultValue="10" alignSelf="CENTER"/>
</hbox>
<hbox id="lookupActions" visible="false">
<button id="selectBtn" action="selectAction"/>
<button id="discardBtn" action="discardAction"/>
</hbox>
</layout>
</view>
loadDelegate
в контроллере экрана переопределен, я данные достаю из БД Clickhouse
:
@Install(to = "trafficsDl", target = Target.DATA_LOADER)
public List<TrafficUiDto> trafficsDlLoadDelegate(final LoadContext<TrafficUiDto> loadContext) {
LoadContext.Query query = loadContext.getQuery();
if (query == null) {
return Collections.emptyList();
}
int offset = query.getFirstResult() / query.getMaxResults();
int limit = query.getMaxResults();
Map<String, Object> conditionsMap = processConditions();
boolean hasNonNullValues = conditionsMap.values().stream().anyMatch(Objects::nonNull);
List<TrafficDto> trafficDtos;
if (hasNonNullValues) {
trafficDtos = trafficService.getFilteredProcessedTraffic(PageRequest.of(offset, limit), conditionsMap);
} else {
Sort.Direction direction = getSortDirection(query.getSort());
if (direction == null) {
trafficDtos = trafficService.getPaginatedProcessedTraffic(PageRequest.of(offset, limit));
} else {
String property = getSortProperty(query.getSort());
trafficDtos =
trafficService.getSortedProcessedTraffic(PageRequest.of(offset, limit), direction, property);
}
}
return mapToUiDto(trafficDtos);
}
Собственно, чтобы стандартно определить список элементов для multiSelectComboBox
, нужно сделать следующее (пример взят из документации):
<multiSelectComboBox metaClass="Hobby"
label="Hobby"
pageSize="30">
<itemsQuery class="com.company.onboarding.entity.Hobby"
escapeValueForLike="true"
searchStringFormat="(?i)%${inputString}%">
<fetchPlan extends="_base"/>
<query>
<![CDATA[select e from Hobby e where e.name
like :searchString escape '\' order by e.name]]>
</query>
</itemsQuery>
</multiSelectComboBox>
У меня так работать не будет. Еще извлечение элементов также может быть определено программно с помощью обработчика itemsFetchCallback
(пример из документации multiSelectComboBox :: Документация Jmix). В этом примере видно, что при помощи dataManager
мы извлекаем все hobbies
. В документации также указано, что компонент подгружает данные как бы лениво получается. Сначала 50 по умолчанию, потом еще 50 и тд. Но если мне нужно выгрузить значения столбца из таблицы на несколько миллионов, а то и десятков-сотен миллионов, что делать тогда? Вытаскивать все эти значения и держать в памяти? Как это будет работать в моем случае? Или мне лучше данный компонент в данном кейс не использовать?
Разъясните, пожалуйста.