Spring Batch - Использование ItemWriter со списком списков

Наш процессор возвращает List<?> (эффективно передавая List<List<?>>) нашим ItemWriter,

Теперь мы заметили, что JdbcBatchItemWriter не запрограммирован на обработку item instanceof List, Мы также наблюдали, чтобы обработать элемент instanceof List; нам нужно написать кастом ItemSqlParameterSourceProvider,

Но грустная часть в том, что он возвращается SqlParameterSource который может обрабатывать только один item и снова не в состоянии справиться с List,

Итак, кто-то может помочь нам понять, как обрабатывать список списков в JdbcBatchItemWriter?

1 ответ

Решение

Как правило, шаблон дизайна:

Reader -> reads something, returns ReadItem
Processor -> ingests ReadItem, returns ProcessedItem
Writer -> ingests List<ProcessedItem>

Если ваш процессор возвращается List<Object>тогда вам нужен ваш писатель List<List<Object>>,

Вы можете сделать это, завернув JdbcBatchItemWriter как делегат в ItemWriter, который выглядит примерно так:

public class ListUnpackingItemWriter<T> implements ItemWriter<List<T>>, ItemStream, InitializingBean {

    private ItemWriter<T> delegate;

    @Override
    public void write(final List<? extends List<T>> lists) throws Exception {
        final List<T> consolidatedList = new ArrayList<>();
        for (final List<T> list : lists) {
            consolidatedList.addAll(list);
        }
        delegate.write(consolidatedList);
    }

    @Override
    public void afterPropertiesSet() {
        Assert.notNull(delegate, "You must set a delegate!");
    }

    @Override
    public void open(ExecutionContext executionContext) {
        if (delegate instanceof ItemStream) {
            ((ItemStream) delegate).open(executionContext);
        }
    }

    @Override
    public void update(ExecutionContext executionContext) {
        if (delegate instanceof ItemStream) {
            ((ItemStream) delegate).update(executionContext);
        }
    }

    @Override
    public void close() {
        if (delegate instanceof ItemStream) {
            ((ItemStream) delegate).close();
        }
    }

    public void setDelegate(ItemWriter<T> delegate) {
        this.delegate = delegate;
    }

}
public class ListUnpackingItemWriter<T> implements FlatFileItemWriter<List<T>>, ItemStream, InitializingBean {

    @Override
    public void afterPropertiesSet() {
        setLineAggregator(item -> String.join("\n", item.stream().map(T::toString).collect(Collectors.toList())));
    }

}

Просто добавил настраиваемый агрегатор строк к вышеуказанному решению, это помогает записывать содержимое в файл с помощью FlatFileItemWriter<List<T>>. Вы можете заменитьT с фактическим именем класса, чтобы избежать ошибки компиляции при вызове toString() метод.

Другие вопросы по тегам