当前位置: 首页 > 面试题库 >

Spring Batch Job从多个来源读取

夏星阑
2023-03-14
问题内容

如何从倍数数据库中读取项目?我已经知道从文件中可以做到。
以下示例适用于从多个文件读取

...
<job id="readMultiFileJob" xmlns="http://www.springframework.org/schema/batch">
    <step id="step1">
    <tasklet>
        <chunk reader="multiResourceReader" writer="flatFileItemWriter"
            commit-interval="1" />
    </tasklet>
    </step>
</job>
...
<bean id="multiResourceReader"
    class=" org.springframework.batch.item.file.MultiResourceItemReader">
    <property name="resources" value="file:csv/inputs/domain-*.csv" />
    <property name="delegate" ref="flatFileItemReader" />
</bean>
...

这样三个豆子

<bean id="database2" class="org.springframework.batch.item.database.JdbcCursorItemReader">
    <property name="name" value="database2Reader" />
    <property name="dataSource" ref="dataSource2" />
    <property name="sql" value="select image from object where image like '%/images/%'" />
    <property name="rowMapper">
        <bean class="sym.batch.ImagesRowMapper2" />
    </property>
</bean>

问题答案:

没有可立即使用的组件可以执行您的要求;唯一的解决方案是编写一个ItemReader<>委托给JdbcCursorItemReader(或委托给或委托HibernateCursorItemReader给任何通用ItemReader实现)的自定义。
您需要准备所有必要的东西(数据源,会话,实际数据库读取器),并将所有委派的读取器绑定到您的自定义读取器。

编辑:您需要使用recussion来模拟一个循环,ItemReader.read()并在整个作业重新启动期间保留阅读器和委托状态。

class MyItemReader<T> implements ItemReader<T>, ItemStream {
  private ItemReader[] delegates;
  private int delegateIndex;
  private ItemReader<T> currentDelegate;
  private ExecutionContext stepExecutionContext;

  public void setDelegates(ItemReader[] delegates) {
    this.delegates = delegates;
  }

  @BeforeStep
  private void beforeStep(StepExecution stepExecution) {
    this.stepExecutionContext = stepExecution.getExecutionContext();
  }

  public T read() {
    T item = null;
    if(null != currentDelegate) {
      item = currentDelegate.read();
      if(null == item) {
        ((ItemStream)this.currentDelegate).close();
        this.currentDelegate = null;
      }
    }
    // Move to next delegate if previous was exhausted!
    if(null == item && this.delegateIndex< this.delegates.length) {
      this.currentDelegate = this.delegates[this.currentIndex++];
      ((ItemStream)this.currentDelegate).open(this.stepExecutionContext);
      update(this.stepExecutionContext);
      // Recurse to read() to simulate loop through delegates
      item = read();
    }
    return item;
  }

  public void open(ExecutionContext ctx) {
    // During open restore last active reader and restore its state
    if(ctx.containsKey("index")) {
      this.delegateIndex = ctx.getInt("index");
      this.currentDelegate = this.delegates[this.delegateIndex];
      ((ItemStream)this.currentDelegate ).open(ctx);
    }
  }

  public void update(ExecutionContext ctx) {
    // Update current delegate index and state
    ctx.putInt("index", this.delegateIndex);
    if(null != this.currentDelegate) {
      ((ItemStream)this.currentDelegate).update(ctx);
    }
  }

  public void close(ExecutionContext ctx) {
    if(null != this.currentDelegate) {
      ((ItemStream)this.currentDelegate).close();
  }
}
<bean id="myItemReader" class=path.to.MyItemReader>
  <property name="delegates">
    <array>
      <ref bean="itemReader1"/>
      <ref bean="itemReader2"/>
      <ref bean="itemReader3"/>
    </array>
  </property>
</bean>

EDIT2:记住设置属性 名称 ;这是让MyItemReader.read()正常工作所必需的

<bean id="itemReader1" class="JdbcCursorItemReader">
  <property name="name" value="itemReader1" />
  <!-- Set other properties -->
</bean>


 类似资料:
  • 我将碰撞矩形(libgdx,而不是awt)设置为球的坐标。我想做的是检查我是否点击了它。两个问题: a.)我不知道矩形坐标的原点在哪里。 b.)我找不到一种正确的方法来校正抽头位置 我能做什么? 根据请求进行编辑:

  • 问题内容: 我有许多文本文件,希望将它们放入for循环中。 我从上一个活动中获得了一个具有资源名称的Extra,并且有一个数组,其原始资源中的文本文件的资源名称来自{d0,d1,d2,d3,…,d79},我想检查名称和数组名称,然后将查找名称放入资源!我的代码(res = R.raw。(d [i]))出现错误: 问题答案: 您可以使用getIdentifier(字符串名称,字符串defType,字

  • 如何修改此ffmpeg字符串以生成具有不同视频比特率的多个输出?这是为了在yadif=1消耗大量电力时节省时间。而且,无法让它在windows中接受yadif_cuda。 ffmpeg-y-f lavfi-i anullsrc=cl=mono:sample_rate=48000-i“test.mxf”-vf yadif=1-s 1920:1080-c:v h264-nvenc-强制关键帧“expr

  • 我需要创建一个带有分页的HTML表。数据来自两个不同的来源(可能是来自两个不同数据库的两个表,比如一个Oracle,另一个是MySQL),您不能使用JOIN select语句。为了使它更复杂,我需要以升序显示按时间戳排序的数据(其中一个属性是timestamp)。 例如,源A有45条记录,源B有55条记录。因此,该表将显示总共100条记录,但一次只显示15条记录。因此必须有7页(6页15条记录,1

  • 问题内容: 我已经在一个类的单个方法中初始化了InputStream,并将其传递给下一个方法进行处理。InputStream本质上封装了CSV文件以进行处理。 另一个方法调用传入同一个InputStream的2个不同方法,一个用于检索标头,另一个用于处理内容。该结构如下所示: 我在这里做错什么了吗?有什么方法可以在不同的方法调用之间重用InputStream。 我正在提出可以模仿以下问题的完整程序

  • 我正在使用python,我有一个文件(