Назначение и особенности использования динамических запросов с шаблонами в 1С на примере интеграции через ESB

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике разработки на платформе 1С:Предприятие, особенно при реализации сложных механизмов обмена данными через корпоративные шины (ESB), программисты часто сталкиваются с кодом, который на первый взгляд кажется некорректным или избыточным. Рассмотрим ситуацию, когда в тексте запроса используются странные конструкции вида Документ.ХХ, и разберемся, какую задачу решает такой подход, какие риски он несет и как сделать его более профессиональным.

Разбор исходного кода и поиск скрытого смысла

Проанализируем фрагмент кода, который вызвал вопросы у автора темы. На первый взгляд, это обычный запрос к метаданным, однако имя таблицы Документ.ХХ явно указывает на то, что перед нами — шаблон. Рассмотрим сам запрос:


Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
               | ХХ.Ссылка
               |ИЗ
               | Документ.ХХ КАК ХХ
               |ГДЕ
               | ХХ.ОжидаемаяПриемка = &ОжидПриемка";
Запрос.УстановитьПараметр("ОжидПриемка", СсылкаНаОбъект);
Результат = Запрос.Выполнить();
Если НЕ Результат.Пустой() Тогда
    // Дальнейшая логика обработки
КонецЕсли;

Выясним причину появления такого кода. Как правило, подобные конструкции используются в универсальных обработчиках. В системах интеграции (например, при получении данных из внешней WMS-системы или другой базы через шину ESB) в 1С приходит пакет данных, содержащий имя типа документа. Чтобы не писать 50 идентичных функций для каждого вида документа, разработчик создает один шаблон запроса.

Как было отмечено в обсуждении, перед выполнением этого кода в программе, скорее всего, вызывается метод СтрЗаменить(), который подставляет вместо ХХ реальное имя документа (например, ПриобретениеТоваровУслуг или ПоступлениеТоваров). Это позволяет использовать один и тот же алгоритм для поиска документов разных типов.

Бизнес-логика: зачем искать документ по реквизиту?

Рассмотрим подробнее сценарий, в котором работает этот код. Реквизит ОжидаемаяПриемка — это ссылка на первичный, плановый документ. В контексте складской логистики (WMS) ситуация выглядит следующим образом:

  1. В систему поступает «План» (Ожидаемая приемка).
  2. На основании этого плана в 1С создается фактический документ (например, «Поступление товаров»).
  3. При повторной выгрузке данных из шины ESB системе нужно проверить: «Был ли уже создан факт под этот конкретный план?».

Запрос ищет ссылку на фактический документ ХХ, у которого в поле ОжидаемаяПриемка записана ссылка на входящий объект. Если Результат.Пустой() возвращает Ложь, значит, документ уже существует, и система может либо обновить его, либо проигнорировать загрузку дубля, обеспечивая тем самым идемпотентность (защиту от повторных срабатываний).

Проблемы производительности и важность индексирования

Проанализируем техническую сторону такого поиска. Когда мы выполняем запрос ГДЕ ХХ.ОжидаемаяПриемка = &ОжидПриемка, критически важно, чтобы в конфигураторе для данного реквизита было включено индексирование.

Если в таблице документа ХХ накоплены сотни тысяч записей, поиск без индекса заставит SQL-сервер выполнять полное сканирование таблицы (Full Scan). В условиях интенсивного обмена через шину данных это гарантированно приведет к:

Поэтому, если вы реализуете подобный механизм, убедитесь, что реквизит, по которому идет поиск, имеет свойство Индексировать или является частью индекса.

Критика «грязного» кода и пути улучшения

Участники форума справедливо назвали использование СтрЗаменить для формирования запроса «говнокодом». Рассмотрим, почему это так, и какие альтернативы предлагает современная платформа 1С:

  1. Отсутствие контроля типов: При замене строк система не проверяет существование документа или реквизита на этапе компиляции. Если в метаданных документ будет переименован, этот код «упадет» только в момент выполнения.
  2. Проблемы с логикой состояний: Как верно замечено в обсуждении, запрос не учитывает пометку на удаление. Если найденный документ помечен на удаление, шина данных может ошибочно посчитать, что данные загружены, хотя фактически они не актуальны.

Правильным подходом будет использование объекта СхемаЗапроса. Посмотрим, как это реализуется программно:


Схема = Новый СхемаЗапроса;
Пакет = Схема.ПакетЗапросов[0];
Оператор = Пакет.Операторы[0];

// Динамически подставляем таблицу на основе имени, полученного из шины
ИмяДокумента = "ПриобретениеТоваровУслуг"; // Значение из параметров интеграции
Оператор.Источники.Добавить("Документ." + ИмяДокумента, "ТекДок");

// Выбираем поле
Пакет.Колонки.Добавить("ТекДок.Ссылка");

// Добавляем условие
Оператор.Отбор.Добавить("ТекДок.ОжидаемаяПриемка = &ОжидПриемка");
Оператор.Отбор.Добавить("НЕ ТекДок.ПометкаУдаления"); // Важное дополнение!

Запрос = Новый Запрос;
Запрос.Текст = Схема.ПолучитьТекстЗапроса();
Запрос.УстановитьПараметр("ОжидПриемка", СсылкаНаОбъект);

Использование СхемаЗапроса позволяет программно и безопасно конструировать текст запроса, избегая манипуляций со строками, которые часто приводят к трудноуловимым ошибкам.

Заключение

Мы выяснили, что странный код с Документ.ХХ — это вынужденная мера для обеспечения универсальности в интеграционных процессах. Однако при его поддержке или рефакторинге важно помнить о проверке состояний документа (проведение, пометка удаления) и обязательной настройке индексов в базе данных. Работа с шинами данных требует от разработчика 1С не только знания синтаксиса запросов, но и понимания архитектуры метаданных в целом.

← На главную