Spring-Batch Многострочная запись Item Writer с переменным количеством строк в записи - PullRequest
4 голосов
/ 20 октября 2011

У меня есть приведенное ниже требование, но я не могу принять решение о подходе:

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

000120992599999990000000000000009291100000000000000000000000010000
000000000000000000000006050052570009700000050000990494920000111100
      ABCDE:WXYZ                                              0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
000000000000000000000006050052730005700001100000090494920000221200
      ABCDE:WXYZ                                              0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
000000000000000000000006050113110009700000000000000494920000311100
      ABCDE:WXYZ                                              0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
000012099259999999000000000000000929110000000000000000000000001000

Это одна запись из приведенного выше примера:

000000000000000000000006050052570009700000050000990494920000111100
      ABCDE:WXYZ                                              0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200
      descriptiongoesheredescriptiongoesheredescriptiongoesher0200

Первая и последняя строки - соответственно верхний и нижний колонтитулы. Первая строка каждой записи содержит несколько деталей. Во 2-й строке есть другие детали с пробелами.

У меня есть поле для длинного описания, которое мне нужно разделить на 56-символьные разделы и добавить те, которые начинаются с 3-й строки записи.

Так что в некоторых записях это может быть только одна строка, а в некоторых это может быть и три строки.

Мне нужно руководство о том, как спроектировать мой itemwriter в приведенном выше сценарии.

Nik

Ответы [ 3 ]

6 голосов
/ 20 октября 2011

в официальном spring-batch-samples есть пример записи многострочных записей, поиск multiline.xml и MultiLineTradeItemWriter

это в принципе обычный принцип делегата, вам просто нужен правильный объект домена с допустимым списком этих 1..n промежуточных строк

    public class MultiLineTradeItemWriter implements ItemWriter<Trade>, ItemStream {

    private FlatFileItemWriter<String> delegate;

    public void write(List<? extends Trade> items) throws Exception {
                List<String> lines = new ArrayList<String>();
              for (Trade t : items) {
              lines.add("BEGIN");
              lines.add("INFO," + t.getIsin() + "," + t.getCustomer());
              lines.add("AMNT," + t.getQuantity() + "," + t.getPrice());
              lines.add("END");
            }
            this.delegate.write(lines);
     }
    }
0 голосов
/ 06 января 2015

У меня была похожая проблема с записью нескольких строк в базу данных. Поскольку шаг задания создаст Список ваших элементов, как вы можете вернуть Список из обработчика автору? Это создаст список списков, и метод doWrite в Writer не настроен для обработки этого сценария.

Я использую 1.2.0 spring-boot-starter-parent (который дает мне spring-core 4.1.3) вместе с hibernate (4.3.7), в моем случае у меня есть «Receables», и для каждого 1 дебиторская задолженность, которую я читаю из CSV-файла, может потребоваться обновить или вставить много дебиторской задолженности в мою таблицу. Я также использую HibernateItemWriter.

Мое решение заключалось в расширении HibernateItemWriter. Поле sessionFactory является закрытым, поэтому я передаю его через конструктор, а также использую метод установки (для размещения существующего кода). Таким образом, мой оригинальный код (который отлично работает для одного «получаемого») изначально выглядел так:

    @Bean
    public ItemWriter<Receivable> recivableWriter() {
        HibernateItemWriter<Receivable> hibernateItemWriter = new HibernateItemWriter<Receivable>(){{ setSessionFactory(sessionFactory); }};
        return hibernateItemWriter;
    }

После расширения HibernateItemWriter и изменения моего процессора, чтобы он возвращал список, мой код изменился на:

    @Bean
    public ItemWriter<List<Receivable>> receivableWriter() {
        HibernateListItemWriter<List<Receivable>> hibernateItemWriter = new HibernateListItemWriter<List<Receivable>>(this.sessionFactory){{ setSessionFactory(sessionFactory); }};
        return hibernateItemWriter;
    }

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

package com.work;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.SessionFactory;

public class HibernateListItemWriter<Receivable> extends org.springframework.batch.item.database.HibernateItemWriter<Receivable> {

    public HibernateListItemWriter(SessionFactory sessionFactory) {
        super();
        this.sessionFactory = sessionFactory;
    }

    private SessionFactory sessionFactory; 
    private boolean clearSession = true;

    @Override
    public void write(List items) {
        List<Receivable> unwrappedItems = new ArrayList<Receivable>();
        List<List<Receivable>> wrappedItems = (List<List<Receivable>>)items;
        for (List<Receivable> singleList: wrappedItems) {
            unwrappedItems.addAll(singleList);
        }
        doWrite(sessionFactory, unwrappedItems);
        sessionFactory.getCurrentSession().flush();
        if(clearSession) {
            sessionFactory.getCurrentSession().clear();
        }
    }

}

Приветствую grepcode.com за облегчение жизни.

0 голосов
/ 17 января 2014

вы можете сделать это в CustomExtractor.

Например:

     public Object[] extract(T item) {
        List<Object> values = new ArrayList<Object>();

        BeanWrapper bw = new BeanWrapperImpl(item);
        for (String propertyName : this.names) {
            values.add( bw.getPropertyValue(propertyName) + "\r\n");
        }
        return values.toArray();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...