Каков наилучший способ сгладить список списков в Spring Batch? - PullRequest
0 голосов
/ 12 марта 2020

В Spring Batch процессоры отображаются из одного типа ввода в один из типа вывода. Однако мне нужно сгенерировать список типов вывода (List<O>) из одного I.

Процессор может нормально вернуть List<O>, но предположим, что я хочу работать с элементами этого списка как отдельные лица в последующих процессорах. Должен ли я сначала записать их в базу данных? На самом деле у меня есть некоторое обогащение от удаленной службы, которое необходимо сделать для каждого члена List<O>, поэтому я не хочу, чтобы они записывались где-либо до тех пор, пока отдельные объекты в списке не будут обработаны.

Это связано с моим предыдущим постом , в котором мне сказали, что @JobScope и передача объектов в памяти между шагами - это 90% запаха кода. Мне любопытно, упускаю ли я здесь специальный шаблон Spring Batch для сглаживания результирующего списка списков, который будет отличаться от записи недоделанных объектов в БД, кэш или плоский файл перед обработкой.

Но в конечном итоге я хочу, чтобы писатель использовал фрагмент O, а не фрагмент List<O>. Так какой подход рекомендуется для этого? До сих пор я придумал следующее, используемое как @JobScope bean:

public class FlatMapPipe<T> implements ItemWriter<List<T>>, ItemReader<T> {

    private LinkedList<List<T>> lists = new LinkedList<List<T>>();

    /**
     * Pages through the internal linked list to find the next item
     * @return next item in the current list or the first item in the next list or null
     * @throws Exception
     * @throws UnexpectedInputException
     * @throws ParseException
     * @throws NonTransientResourceException
     */
    @Override
    public T read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        if (lists.size() == 0) {
            return null;
        }
        List<T> list = lists.get(0);
        if (list.isEmpty()) {
            lists.remove();
            return read();
        } else {
            return list.remove(0);
        }
    }

    /**
     * Appends a list to the linked list of lists of written Items
     * @param list
     * @throws Exception
     */
    @Override
    public void write(List<? extends List<T>> list) throws Exception {
        list.forEach((it) -> lists.add(new ArrayList<>(it)));
    }
} 

1 Ответ

0 голосов
/ 12 марта 2020

Процессор может нормально возвращать список, но предположим, что я хочу работать с элементами этого списка как отдельные лица в последующих процессорах. Должен ли я сначала записать их в базу данных?

Нет необходимости сначала записывать их в базу данных, это было бы неэффективно. Инкапсуляция - ваш друг, вы можете обернуть результат вашего процессора в агрегатный тип, который можно передать последующим процессорам в цепочке (например, с использованием составного процессора). Затем создатель элемента отвечает за выполнение операции плоской карты, чтобы развернуть полностью обработанные элементы из агрегатного типа перед их записью.

Другой метод заключается в использовании двух одновременных шагов с областью подготовки (где вы должны сгладить элементы) как описано в выпуск № 2044 . Я реализовал Po C здесь с очередью блокировки в качестве промежуточной области. В вашем случае первый шаг будет обрабатывать элементы и записывать результаты в очередь, а второй шаг может считывать (плоские) элементы из очереди, обогащать их по мере необходимости и записывать их в случае необходимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...