Springbatch动态多xml文件编写器
我必须做一批:Springbatch动态多xml文件编写器,xml,output,spring-batch,partitioner,Xml,Output,Spring Batch,Partitioner,我必须做一批: 从数据库中读取一些数据(每行都是一个项目,这很好) 然后执行一些过程来添加更多数据(数据越多越好;) 然后是我的问题,我必须将每个项目写入一个xml文件中,谁的名字取决于项目的数据 例如,我有 ItemA(attr1=toto,attr2=foo,attr3=myNonKeyData…)=>进入toto_foo.xml ItemB(attr1=toto,attr2=foo,attr3=myNonKeyData…)=>放在toto_foo.xml中 ItemC(attr1=tata
从数据库中读取一些数据(每行都是一个项目,这很好)
然后执行一些过程来添加更多数据(数据越多越好;)
然后是我的问题,我必须将每个项目写入一个xml文件中,谁的名字取决于项目的数据 例如,我有
ItemA(attr1=toto,attr2=foo,attr3=myNonKeyData…)=>进入toto_foo.xml
ItemB(attr1=toto,attr2=foo,attr3=myNonKeyData…)=>放在toto_foo.xml中 ItemC(attr1=tata,attr2=foo…)=>放在tata\u foo.xml中
... 我看不出如何在只运行一次批处理的情况下执行此操作。
我有太多的键和可能的输出文件,无法进行分类器。
也许使用分区器可能是个好主意,即使它似乎不是为此而设计的。这就是我所理解的
- 任意数量的文件
- 一次性处理数据库中的数据-从数据库中读取一次并写入多个文件
- 正在写入的项的一个或多个属性确定要写入的目标文件的名称
public class MyCompositeItemWriter<T> implements ItemStreamWriter<T> {
// The String key is the file-name(toto_foo.xml, tata_foo.xml etc)
//The map will be empty to start with as we do not know how many files will be created.
private Map<String, ItemWriter<? super T>> delegates;
private boolean ignoreItemStream = false;
public void setIgnoreItemStream(boolean ignoreItemStream) {
this.ignoreItemStream = ignoreItemStream;
}
@Override
public void write(List<? extends T> items) throws Exception {
for(T item : items) {
ItemWriter<? super T> writer = getItemWriterForItem(item);
// Writing one item ata time might be inefficent. You can optimize this by grouping items by fileName.
writer.write(item);
}
}
private getItemWriterForItem(T item) {
String fileName = getFileNameForItem(item);
ItemWriter<? super T> writer = delegates.get(fileName);
if(writer == null) {
// There is no writer for the fileName.
//create one
writer = createMyItemWriter(fileName);
delegates.put(fileName, writer);
}
return writer;
}
ItemWriter<? super T> createMyItemWriter(String fileName) {
// create the writer. Maybe a org.springframework.batch.item.xml.StaxEventItemWriter
// set the resource(fielName)
//open the writer
}
// Identify the name of the target file - toto_foo.xml, tata_foo.xml etc
private String getFileNameForItem(Item item) {
.....
}
@Override
public void close() throws ItemStreamException {
for (ItemWriter<? super T> writer : delegates) {
if (!ignoreItemStream && (writer instanceof ItemStream)) {
((ItemStream) writer).close();
}
}
}
@Override
public void open(ExecutionContext executionContext) throws ItemStreamException {
// Do nothing as we do not have any writers to begin with.
// Writers will be created as needed. And will be opened after creation.
}
@Override
public void update(ExecutionContext executionContext) throws ItemStreamException {
for (ItemWriter<? super T> writer : delegates) {
if (!ignoreItemStream && (writer instanceof ItemStream)) {
((ItemStream) writer).update(executionContext);
}
}
}
公共类MyCompositeItemWriter实现ItemStreamWriter{
//字符串键是文件名(toto_foo.xml、tata_foo.xml等)
//地图将是空的开始,因为我们不知道有多少文件将被创建。
private Map为什么让编写器决定要写入的文件是一个问题?另外。也许您想详细说明处理器的“更多数据”如何与编写器交互。很好!我更改了写入方法,因为它在所有文件中写入所有内容。我逐个写入元素(我在列表中只保留一项,好的一项),由于我没有数千个项目,这是可以的。许多thxBrilliant的想法。将尝试它。另一个带有FlatFileItemWriter的示例在这里可用