Как написать несколько XML-файлов для дочерних компонентов в Spring Batch ItemWriter? - PullRequest
0 голосов
/ 24 октября 2019

У меня есть пакетное задание, которое извлекает записи из базы данных, обрабатывает их и передает результат в программу записи. У bean-компонента, переданного разработчику, есть четыре поля, которые необходимо записать в отдельные файлы XML. Одним из полей является bean-компонент, представляющий исходную запись, а остальные три поля являются коллекциями дочерних элементов, связанных с этой записью.

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

Далее я перешел к использованию StaxEventItemWriter s для каждого дочернего поля, что по отдельности кажется вполне адекватным, но у меня возникают проблемы с реализацией писателя. который может обрабатывать все различные подтипы. Я посмотрел на CompositeItemWriter и ClassifierCompositeItemWriter, но они кажутся более подходящими для того, чтобы иметь несколько писателей для одного и того же типа бобов, тогда как мне нужно несколько писателей, подходящих для разных типов. Буду признателен за любой совет!

Пример домена:

public class MyBean {
    private RecordBean recordBean;
    private List<ChildTypeA> aBeans;
    private List<ChildTypeB> bBeans;
    private List<ChildTypeC> cBeans;
}

@XmlRootElement(name = "RECORD")
public class RecordBean extends MyAbstractBean {
    @XmlElement(name = "ID")
    private String recordId;

    @XmlElementWrapper(name = "A_CHILDREN")
    @XmlElement(name="CHILD_TYPE_A")
    List<Long> aChildIds}

    @XmlElementWrapper(name = "B_CHILDREN")
    @XmlElement(name="CHILD_TYPE_B")
    List<Long> bChildIds}

    @XmlElementWrapper(name = "C_CHILDREN")
    @XmlElement(name="CHILD_TYPE_C")
    List<Long> cChildIds}
}

@XmlRootElement(name = "CHILD_TYPE_A")
public class ChildTypeA extends MyAbstractBean {
    @XmlElement(name = "ID") private String aId;
}

@XmlRootElement(name = "CHILD_TYPE_B")
public class ChildTypeB extends MyAbstractBean {
    @XmlElement(name = "ID") private String bId;
}

@XmlRootElement(name = "CHILD_TYPE_C")
public class ChildTypeC extends MyAbstractBean {
    @XmlElement(name = "ID") private String cId;
}

Для каждого контейнерного компонента, передаваемого в устройство записи, мне нужно создать уникальный файл XML для каждого RecordBean, например, record_1. xml, и мне нужно записать каждую коллекцию в сводный файл, который будет служить библиотекой всех дочерних элементов для этого дочернего типа для всех записей.

Пример вывода: record_1.xml

<?xml version="1.0" encoding="UTF-8"?>
<RECORD>
    <ID>1</ID>
    <A_CHILDREN>
        <CHILD_TYPE_A>1</CHILD_TYPE_A>
        <CHILD_TYPE_A>2</CHILD_TYPE_A>
    </A_CHILDREN>
    <B_CHILDREN>
        <CHILD_TYPE_B>1</CHILD_TYPE_B>
        <CHILD_TYPE_B>2</CHILD_TYPE_B>
    </B_CHILDREN>
    <A_CHILDREN>
        <CHILD_TYPE_C>1</CHILD_TYPE_C>
        <CHILD_TYPE_C>2</CHILD_TYPE_C>
    </A_CHILDREN>
</RECORD>
</xml>

record_2.xml

<?xml version="1.0" encoding="UTF-8"?>
<RECORD>
    <ID>2</ID>
    <A_CHILDREN>
        <CHILD_TYPE_A>3</CHILD_TYPE_A>
        <CHILD_TYPE_A>4</CHILD_TYPE_A>
    </A_CHILDREN>
    <B_CHILDREN>
        <CHILD_TYPE_B>3</CHILD_TYPE_B>
        <CHILD_TYPE_B>4</CHILD_TYPE_B>
    </B_CHILDREN>
    <A_CHILDREN>
        <CHILD_TYPE_C>3</CHILD_TYPE_C>
        <CHILD_TYPE_C>4</CHILD_TYPE_C>
    </A_CHILDREN>
</RECORD>
</xml>

a_children.xml

<?xml version="1.0" encoding="UTF-8"?>
<A_CHILDREN>
    <CHILD_TYPE_A>
        <ID>1</ID>
    </CHILD_TYPE_A>
    <CHILD_TYPE_A>
        <ID>2</ID>
    </CHILD_TYPE_A>
    <CHILD_TYPE_A>
        <ID>3</ID>
    </CHILD_TYPE_A>
    <CHILD_TYPE_A>
        <ID>4</ID>
    </CHILD_TYPE_A>
</A_CHILDREN>
</xml>
<!-- Decide which format to use -->

b_children.xml & c_children.xml аналогичны a_children.xml.

1 Ответ

0 голосов
/ 30 октября 2019

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

Например:

  • CompositeItemWriter делегирует:
    • ClassifierCompositeItemWriter классифицирует и делегирует:
      • StaxEventItemWriter для ChildTypeA
      • StaxEventItemWriter для ChildTypeB
      • StaxEventItemWriter для ChildTypeC
    • MultiResourceItemWriter Динамически назначает FilesystemResource для каждого RecordBean.

Несмотря на то, что онвероятно, можно было бы сделать, я понял, что просто написать XML в виде строк, где я хочу. Что-то вроде:

@Component
@Scope("step")
public class MyXmlWriter implements ItemWriter<MyBean> {
    @Override
    public void write(List<? extends MyBean> beans) throws Exception {
        for(MyBean bean : beans) {
            this.writeRecordBean(bean.getRecordBean());
            bean.getAChildIds().forEach(a -> this.writeElement(a, pathA));
            bean.getBChildIds().forEach(b -> this.writeElement(b, pathB));
            bean.getCChildIds().forEach(c -> this.writeElement(c, pathC));
        }
    }

    private void writeElement(Long Id, Path path) {
        // Handle serialization and FileIO here
    }

    .
    .
    .

}

В любом случае, я надеюсь, что это поможет любому, кто копается в сорняках Весенней партии, как я. Ура!

...