77

Spring Batch を掘り下げて、ジョブのさまざまなステップ間でデータを共有するにはどうすればよいですか?

これに JobRepository を使用できますか? はいの場合、どうすればそれを行うことができますか?

同じことを行う/達成する他の方法はありますか?

4

12 に答える 12

44

ジョブリポジトリは、ステップ間でデータを渡すために間接的に使用されます(Jean-Philippeは、データをに入れてからStepExecutionContext、冗長な名前ExecutionContextPromotionListenerを使用してステップ実行コンテキストキーをにプロモートするのが最善の方法JobExecutionContextです。

JobParameterキーをに昇格させるためのリスナーもあることに注意してくださいStepExecutionContext(さらに詳細に名前が付けられていますJobParameterExecutionContextCopyListener)。あなたの仕事のステップが互いに完全に独立していない場合、あなたはこれらをたくさん使うことに気付くでしょう。

そうしないと、JMSキューや(天国では禁止されている)ハードコードされたファイルの場所など、さらに複雑なスキームを使用してステップ間でデータを渡すことになります。

コンテキストで渡されるデータのサイズについては、小さくすることをお勧めします(ただし、詳細については説明していません。

于 2010-05-07T20:58:17.387 に答える
43

ステップから、データを に入れることができますStepExecutionContext。次に、リスナーを使用して、データを からStepExecutionContextにプロモートできますJobExecutionContext

これJobExecutionContextは、次のすべての手順で使用できます。

注意: データは短くする必要があります。これらのコンテキストはJobRepositoryシリアル化によって保存され、長さは制限されています (よく覚えていれば 2500 文字)。

したがって、これらのコンテキストは、文字列や単純な値を共有するには適していますが、コレクションや大量のデータを共有するには適していません。

大量のデータを共有することは、Spring Batch の哲学ではありません。Spring Batch は一連の個別のアクションであり、巨大なビジネス処理ユニットではありません。

于 2010-03-30T11:25:21.727 に答える
26

3つのオプションがあると思います:

  1. それを使用StepContextして昇格さJobContextせ、各ステップからアクセスできるようにします。サイズの制限に従う必要があります。
  2. Bean を作成@JobScopeし、その Bean にデータを追加し@Autowire、必要に応じて使用します (欠点は、メモリ内構造であり、ジョブが失敗するとデータが失われ、再起動性に問題が生じる可能性があることです)。
  3. ステップ全体で処理する必要があるより大きなデータセット (csv の各行を読み取り、DB に書き込む、DB から読み取り、集約して API に送信する) が必要だったため、Spring バッチ メタ テーブルと同じ DB の新しいテーブルでデータをモデル化し、保持することにしました。必要idsJobContext応じてアクセスし、ジョブが正常に終了したらその一時テーブルを削除します。
于 2015-03-14T11:32:21.817 に答える
8

Java Bean オブジェクトを使用できます

  1. 1ステップ実行
  2. 結果を Java オブジェクトに格納する
  3. 次のステップでは、同じ Java オブジェクトを参照して、ステップ 1 で保存された結果を取得します。

このようにして、必要に応じて膨大なデータのコレクションを保存できます

于 2012-02-03T18:56:23.117 に答える
4

別の非常に単純なアプローチです。将来の参照用にここを残します。

class MyTasklet implements Tasklet {
    @Override
    public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) {
        getExecutionContext.put("foo", "bar");
    }
}

class MyOtherTasklet implements Tasklet {
    @Override
    public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) {
        getExecutionContext.get("foo");
    }   
}

getExecutionContextここは:

ExecutionContext getExecutionContext(ChunkContext chunkContext) {
    return chunkContext.getStepContext()
                       .getStepExecution()
                       .getJobExecution()
                       .getExecutionContext();
}     

それをスーパークラスに入れたり、インターフェースにdefaultメソッドとして入れたり、単純に s に貼り付けたりしますTasklet

于 2018-11-29T15:22:36.793 に答える
1

バッチ ジョブを 1 つずつ呼び出すタスクが与えられました。各ジョブは別のジョブに依存しています。最初のジョブ結果は、結果ジョブ プログラムを実行する必要があります。ジョブ実行後にデータを渡す方法を探していました。この ExecutionContextPromotionListener が便利であることがわかりました。

1)以下のように「ExecutionContextPromotionListener」のBeanを追加しました

@Bean
public ExecutionContextPromotionListener promotionListener()
{
    ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
    listener.setKeys( new String[] { "entityRef" } );
    return listener;
}

2)次に、リスナーの1つをステップに接続しました

Step step = builder.faultTolerant()
            .skipPolicy( policy )
            .listener( writer )
            .listener( promotionListener() )
            .listener( skiplistener )
            .stream( skiplistener )
            .build();

3) Writer ステップの実装に参照として stepExecution を追加し、Beforestep に入力しました。

@BeforeStep
public void saveStepExecution( StepExecution stepExecution )
{
    this.stepExecution = stepExecution;
}   

4)ライターステップの最後に、以下のようなキーとしてステップ実行に値を入力しました

lStepContext.put( "entityRef", lMap );

5) ジョブの実行後、から値を取得し、 lExecution.getExecutionContext()ジョブの応答として入力しました。

6) ジョブ応答オブジェクトから値を取得し、残りのジョブに必要な値を入力します。

上記のコードは、ExecutionContextPromotionListener を使用してステップから ExecutionContext にデータを昇格させるためのものです。任意のステップで実行できます。

于 2016-02-08T07:34:03.523 に答える