コンテキスト春のバッチカスタム完了ポリシー
我々は外部のものから私たちのDBにローカライズされた国の名前(異なる言語の国名のすなわち翻訳)を複製バッチジョブを持っています。 1つのチャンク(つまり、最初のチャンク - アンドラのすべての翻訳、次のチャンク、U.A.E.のすべての翻訳など)で1つの国のすべてのローカライズされた国名を処理することでした。私たちは、国のために利用できる翻訳の合計数を提供するために、いくつかのOracleの分析関数は+外部データを読み込むためのJdbcCursorItemReader
を使用します。
select country_code, language_code, localized_name, COUNT(1) OVER(PARTITION BY c_lng.country_code) as lng_count
from EXT_COUNTRY_LNG c_lng
order by c_lng.countty_code, c_lng.language_code
ような何か問題
だから塊で、この入力を切断するのは簡単になります。停止チャンクlng_count
で指定された行の正確な量を読み取り、次の行で新しい行を開始すると、実際にはそれほど単純ではないように見えます:(
最初に試すものはカスタム完了ポリシーです。問題は、 ItemReader
で読んだ最後の項目にアクセスすることはできません。明示的にそれを読者のコンテキストに置き、ポリシーに戻す必要があります。追加のリーダーの変更/リーダーリスナーの追加が必要なため、好きではありません。さらに、私は、同じアイテムが前後に直列化/逆直列化されているのが好きではありません。そして、私はJobContext
/StepContext
がそのようなデータのためのよい場所であるように感じません。
我々はこのようなソリューションになってしまうので、最後に...
をそこにも、このようなデータのためのより良い場所のように見えますRepeatContext
だが、私はそれが簡単にに取得することができませんでした:
@Bean(name = "localizedCountryNamesStep")
@JobScope
public Step insertCountryStep(
final StepBuilderFactory stepBuilderFactory,
final MasterdataCountryNameReader countryNameReader,
final MasterdataCountryNameProcessor countryNameProcessor,
final MasterdataCountryNameWriter writer) {
/* Use the same fixed-commit policy, but update it's chunk size dynamically */
final SimpleCompletionPolicy policy = new SimpleCompletionPolicy();
return stepBuilderFactory.get("localizedCountryNamesStep")
.<ExtCountryLng, LocalizedCountryName> chunk(policy)
.reader(countryNameReader)
.listener(new ItemReadListener<ExtCountryLng>() {
@Override
public void beforeRead() {
// do nothing
}
@Override
public void afterRead(final ExtCountryLng item) {
/* Update the cunk size after every read: consequent reads
inside the same country = same chunk do nothing since lngCount is always the same there */
policy.setChunkSize(item.getLngCount());
}
@Override
public void onReadError(final Exception ex) {
// do nothing
}
})
.processor(countryNameProcessor)
.writer(writer)
.faultTolerant()
.skip(RuntimeException.class)
.skipLimit(Integer.MAX_VALUE) // Batch does not support unlimited skip
.retryLimit(0) // this solution disables only retry, but not recover
.build();
}
動作していますが、コードを最小限変更する必要がありますが、まだまだ私にとっては醜いです。だから私は、すべての必要な情報が既にItemReader
で利用可能なときにバネバッチでダイナミックチャンクサイズを実行する別のエレガントな方法があるのだろうかと疑問に思っていますか?
afterReadはchunkksizeを変更するための適切な場所ではなく、次のチャンクで有効にするためにafterWriteに配置します。 –
論理的にはafterWriteが正しく発音されますが、1)チャックを書き込んだ後はその情報はありません余分なDBクエリなし2)最初のチャンクのサイズは何とか決定されるべきです - 別の追加のDBクエリ? –
プロセスの前にターゲットテーブルを拭き取りますか?それともこれはただの仕事ですか? –