1

データベース内の一連の行を取得し、それらの行からファイルごとに 10 行の多数のフラット ファイルを作成する Spring Batch プロセスがあります。これを行うために、次のような 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

出力には2つのファイルが期待されますが、


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

入力ファイルに 2 行ある場合はすべて正常に機能しますが、2 行を超えると機能しません。commit-interval を 200 に変更すると、1 つのファイルに 3 行が表示されますが、これは望ましい動作ではありません。

私が何か間違ったことをしている場合、または問題を回避する方法がない場合は、誰かが私に教えてくれたら、とても感謝しています.

4

2 に答える 2

3

実際、これはバグです。http://jira.springframework.org/browse/BATCH-1452を参照してください。

Dave Syerによると、回避策は次のとおりです。

IOException は厄介です。部分的な回避策は、FlatFileItemWriter で新しいトランザクション プロパティを使用し、false に設定することです (BATCH-1449)。ただし、再起動可能性が失われます (それが問題でなければ、問題ありません)。2.1に合わせて修正してみます。

もう 1 つの回避策は、別の手順でファイルを後処理することです (ヘッダー/フッターのコールバックは使用しません)。

カウントの問題 (ファイルごとに 2 つ以上のアイテム) は、実際には別のものです。マルチリソース ライターは、ファイルごとの正確なアイテム数を保証するようには設計されておらず、制限に違反した場合にのみスピルオーバーします。必要に応じて、強化のために JIRA を開くことができます。回避策は、例で commit-interval="2" を使用することです (または、より一般的には、目的のファイル サイズの要素)。

于 2009-11-27T08:40:31.540 に答える
1

db からデータを読み取ってファイルに書き込もうとしているとします。このシナリオでは、データをファイルに書き込むときに、「HeaderFooterCallback」ファイルで使用するオブジェクトが必要です。これどうやってやるの ?

于 2011-09-22T14:43:24.773 に答える