Массовая обработка#
Описание раздела#
Скрипты и шаблоны для обработки больших объёмов данных в JEXL. Используются при миграции, пересчёте, восстановлении или массовом обновлении записей. Содержат примеры работы с ElExpOQuery, Btk_BulkProcessPkg и передачи Scala-объектов через MODULE$.
Скрипты#
Шаблон массовой обработки через ElExpOQuery#
Используется как основа для написания производительных JEXL-скриптов, обрабатывающих тысячи записей. Демонстрирует использование объектного запроса ElExpOQuery для пакетной загрузки сущностей и обработки по чанкам.
Место применения: Сервис > Инструменты > Выполнить JEXL-скрипт
Внимание
Требует адаптации под конкретную сущность и версию системы. Перед использованием убедитесь, что целевой API (например, Co_ProdCostDocEntryApi) и соответствующие Scala-объекты доступны в вашей версии платформы.
Тип: JEXL-скрипт
const vDocApi = Co_ProdCostDocEntryApi;
const mkDocOQuery = (idap) => {
const vOQ = new ru.bitec.app.gtk.eclipse.query.ElExpOQuery(vDocApi);
const idavAL = new java.util.ArrayList();
idap.foreach(idv => idavAL.add(idv));
vOQ.forWhere(vBuilder => vBuilder.get("id").in(idavAL.toArray()) );
vOQ.batchIn(
asScala([session.sbtClassLoader().loadClass("ru.bitec.app.co.prodcostdocentry.Co_ProdCostDocEntryDetAta$").MODULE$, ...])
);
return vOQ;
};
asScala(sql(`
select t.id
from Co_ProdCostDocEntry t
where t.dDoc is not null
and t.idStateMC >= 300
`).asList()).grouped(400).foreach(ravBatch => {
mkDocOQuery(ravBatch.map(r => r.id)).foreach(ropDoc => {
Co_ProdCostRegFullApi.createItemsByDoc(ropDoc, ropDoc.dDoc);
});
commit();
});
Шаблон массовой обработки через Btk_BulkProcessPkg#
Используется как основа для массовой обработки записей с автоматическим разбиением на чанки. Демонстрирует применение Btk_BulkProcessPkg.chunkedQuery для безопасной работы с большими выборками без переполнения памяти.
Место применения: Сервис > Инструменты > Выполнить JEXL-скрипт
Внимание
Требует адаптации под конкретную сущность и версию системы. Классы Scala-объектов (например, Co_ProdCostDocEntryDetAta$) могут отсутствовать или измениться в новых версиях платформы.
Тип: JEXL-скрипт
Btk_BulkProcessPkg.chunkedQuery(
Co_ProdCostDocEntryApi,
5000L,
`select t.id from Co_ProdCostDocEntry t`,
asScala([...]), // Неизвестен способ передачи NamedParameter из JEXL
asScala([session.sbtClassLoader().loadClass("ru.bitec.app.co.prodcostdocentry.Co_ProdCostDocEntryDetAta$").MODULE$, ...]),
false,
false,
ropa => {
ropa.foreach(rop => Btk_InfoLogPkg.info(rop.gid));
}
);
Обработка данных пакетами#
Обрабатывает записи по частям, без загрузки всего набора данных в память приложения.
Скрипт показывает подход для массового изменения большого объема данных, когда обработка всех записей за один проход может привести к переполнению памяти и остановке веб-приложения. Записи выбираются и обрабатываются пачками. После обработки каждой пачки выполняется commit(), затем запрашивается следующая часть данных.
Такой подход полезен, например, когда нужно изменить значения поля в таблице с очень большим количеством записей.
Место применения: Сервис > Инструменты > Выполнить JEXL-скрипт
Тип: JEXL-скрипт
// Обработка данных по пачкам
var batchSize = 200;
var nCount = 0;
var nOffset = 0;
var sqlText = `
<запрос>
`;
while (true) {
// offset не нужен, если после каждой пачки отдается commit в БД
// и запрос исключает уже обработанные записи
var listSQL = sql(sqlText + " offset " + nOffset + " limit " + batchSize).asList();
// Условие выхода из цикла
if (listSQL.isEmpty()) {
break;
}
for (data : listSQL) {
var ropPlacement = Bs_PlacementApi.load(data.id);
Bs_PlacementApi.setObjAttrValue(ropPlacement, "idMonitorTrainLocationType", data.idtype);
nCount += 1;
}
commit();
nOffset += batchSize;
}
// Результат
if (nCount == 0) {
dialogs.showMessage("Исправлять нечего.");
} else {
dialogs.showMessage("Исправлено " + nCount + " записей.");
}