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()
метод.