我有一个Spring Batch进程,该进程在数据库中获取一组行,并从这些行创建许多平面文件,每个文件10行。为此,我创建了一个Spring Batch流程,类似于:
<batch:job id="springTest" job-repository="jobRepository" restartable="true">
<batch:step id="test">
<batch:tasklet>
<batch:chunk reader="itemReader" writer="multipleItemWriter" commit-interval="2" />
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="itemReader" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="file:/temp/temp-input.txt" />
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.PassThroughLineMapper" />
</property>
</bean>
<bean id="multipleItemWriter" class="org.springframework.batch.item.file.MultiResourceItemWriter">
<property name="resource" value="file:/temp/temp-out" />
<property name="itemCountLimitPerResource" value="2" />
<property name="delegate">
<bean id="itemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter">
<property name="lineAggregator">
<bean class="org.springframework.batch.item.file.transform.PassThroughLineAggregator" />
</property>
<property name="encoding" value="utf-8" />
<property name="headerCallback" ref="headerFooter" />
<property name="footerCallback" ref="headerFooter" />
</bean>
</property>
</bean>
<bean id="headerFooter" class="uk.co.farwell.spring.HeaderFooterCallback" />
以上示例从平面文件中读取并输出到平面文件(以显示问题)。请注意块中的commit-interval = 2,以及MultiResourceItemWriter中的itemCountLimitPerResource = 2。
HeaderFooterCallback执行以下操作:
public void writeHeader(Writer writer) throws IOException {
writer.write("file header\n");
}
public void writeFooter(Writer writer) throws IOException {
writer.write("file footer\n");
}
我需要能够准确指定文件中出现的行数。
对于以下输入文件:
foo1
foo2
foo3
我希望输出两个文件,
out.1:
file header
foo1
foo2
file footer
out.2:
file header
foo3
file footer
当我使用commit-interval = 2运行时,我得到一个例外:
2009-11-26 15:32:46,734 ERROR .support.TransactionSynchronizationUtils - TransactionSynchronization.afterCompletion threw exception
org.springframework.batch.support.transaction.FlushFailedException: Could not write to output buffer
at org.springframework.batch.support.transaction.TransactionAwareBufferedWriter$1.afterCompletion(TransactionAwareBufferedWriter.java:71)
at org.springframework.transaction.support.TransactionSynchronizationUtils.invokeAfterCompletion(TransactionSynchronizationUtils.java:157)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.invokeAfterCompletion(AbstractPlatformTransactionManager.java:974)
.
.
.
Caused by: java.io.IOException: Stream closed
at sun.nio.cs.StreamEncoder.ensureOpen(Unknown Source)
at sun.nio.cs.StreamEncoder.write(Unknown Source)
at sun.nio.cs.StreamEncoder.write(Unknown Source)
at java.io.Writer.write(Unknown Source)
at org.springframework.batch.support.transaction.TransactionAwareBufferedWriter$1.afterCompletion(TransactionAwareBufferedWriter.java:67).
我认为这是一个错误。很奇怪,文件如下:
out.1:
file header
foo1
foo2
out.2:
file footer
如果输入文件中有两行,则一切正常,但两个以上不起作用。如果我将commit-interval更改为200,那么我在一个文件中得到三行,这不是所需的行为。
如果有人能告诉我,如果我做错了,或者如果不能解决问题,我会非常感激。
答案 0 :(得分:3)
实际上,这是一个错误。请参阅http://jira.springframework.org/browse/BATCH-1452。
根据Dave Syer,解决方法是:
IOException很讨厌。部分 解决方法是使用新的 交易财产 FlatFileItemWriter,将其设置为 假(BATCH-1449)。但是你失败了 可重启性(如果那不是一个 问题你很高兴去)。我会尽力 并正确地修复2.1。
另一种解决方法是发布流程 文件在一个单独的步骤(而不是 使用页眉/页脚回调)。
计票问题(超过2项 每个文件)真的是分开的 - 多资源作家永远不会 旨在保证精确 每个文件的项目数,仅限于 如果违反限制则溢出。 您可以打开JIRA进行增强 如果你愿意,可以使用一种解决方法 在您的示例中,commit-interval =“2” (或更一般地说是一个因素 所需的文件大小)。
答案 1 :(得分:1)
考虑一下,您正在尝试从db读取数据并将其写入文件。在这种情况下,当您将数据写入文件时,需要在“HeaderFooterCallback”文件中使用一个对象。你是怎么做到的?