Spring批处理作业从多个来源读取

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

...        ...     ... 

像这样的三个豆子。

         

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

编辑:您需要使用ItemReader.read ItemReader.read()和mantain reader的ItemReader.read()来模拟循环,并在作业重新启动时委托状态。

 class MyItemReader implements ItemReader, ItemStream { private ItemReader[] delegates; private int delegateIndex; private ItemReader 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(); } } 

          

EDIT2:记得设置属性名称 ; 让MyItemReader.read()正常工作是必要的

     

我建议一个简单的解决方法,可能不适合所有情况,但在许多情况下会有用:

简单定义:

  • 2个读者,每个数据库一个
  • 2个步骤
  • 一个包含两个步骤的工作

这两个步骤几乎完全相同,它们引用相同的处理器和写入器,但它们具有不同的读取器。 它们将被连续调用。

此设置是否有效取决于处理器和编写器(在不同步骤中调用时它们是否仍能正常工作)。 在我的例子中,将appendAllowed=true设置为writer就足够了,这样两个步骤都可以写入同一个文件。

我建议一个棘手的方法。 如果我们假设一个是您的mysql数据源的表是基础的,并且该表中的每一行都对应于其他mysql数据源表的行(就像位于不同数据源中的连接表),您可以在批处理作业项目读取器中执行此操作。 除此之外;

Spring DataSource配置;

               

你的batch-job.xml

      SELECT * FROM xyz        SELECT * FROM abc    

你的RowMapper看起来像;

 public class MultiDatasourceRowMapper implements RowMapper { private DataSource secondDataSource; private String secondSql; public String mapRow(ResultSet rs, int arg1) throws SQLException { Connection conn = secondDataSource.getConnection(); PreparedStatement prep = conn.prepareStatement(secondSql); // Do Something return ""; } public void setSecondDataSource(DataSource secondDataSource) { this.secondDataSource = secondDataSource; } public void setSecondSql(String secondSql) { this.secondSql = secondSql; } }