【问题标题】:Spring Batch: Multiple Item Readers in a single stepSpring Batch:一步中的多个项目阅读器
【发布时间】:2017-01-15 09:21:49
【问题描述】:

我是春季批次的新手。我在spring batch中需要完成的任务如下:

  1. 需要从数据库中读取一些元数据。
  2. 基于这个元数据,我需要读取一些文件。
  3. 经过一些处理,需要将这些值从文件写入数据库。

我的查询如下:

一个。对于第一个要求,我需要将整个结果集映射到单个对象,其中与人员相关的数据在 1 个表中,与宠物相关的数据在另一个表中,并通过人员 ID 连接。

public class PersonPetDetails {

    private String personName;
    private String personAddr;

    private int personAge;

    private List<Pet> pets;

为此,我编写了一个自定义项目阅读器,它扩展了 JdbcCursorItemReader。

public class CustomJDBCCusrorItemReader<T> extends JdbcCursorItemReader<T> {

    private ResultSetExtractor<T> resultSetExtractor;


    public void setResultSetExtractor(ResultSetExtractor<T> resultSetExtractor) {
        this.resultSetExtractor = resultSetExtractor;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        setVerifyCursorPosition(false);
        Assert.notNull(getDataSource(), "DataSource must be provided");
        Assert.notNull(getSql(), "The SQL query must be provided");
        Assert.notNull(resultSetExtractor, "ResultSetExtractor must be provided");
    }


    @Override
    protected T readCursor(ResultSet rs, int currentRow) throws SQLException {      
        return resultSetExtractor.extractData(rs);
    }
}

这是实现我的要求的正确方法吗?还是有更好的方法?

b. AFAIK,在春季批次中,只有一个读者,没有一个作家,就不可能有一步。因此,我不能在工作的不同步骤中调用另一组读者。那么,如何一步调用多个阅读器呢?

c。另外,根据某些情况,我可能需要调用第三组 Reader。如何在一个步骤中有条件地调用读者?

感谢您浏览我的帖子。我知道它很长。任何帮助深表感谢。另外,我想一个示例代码 sn-p 将帮助我更好地理解这一点。 :)

【问题讨论】:

  • 我的第一个建议是将您的问题分成多个问题,因为点 a) b) 和 c) 完全不相关。 a) 可以使用通过扩展的委托来解决 b) 在某些情况下可以使用多个读取器(例如stackoverflow.com/questions/21304364/…) c) SB 中的条件使用 JobExecutionDecider 解决

标签: java spring-batch


【解决方案1】:

我会推荐如下

高级设计:

  1. 分区器 它将处理人员列表。注意:此时没有提取宠物数据。

  2. 阅读器 它将获得属于一个人的宠物列表。注意:阅读器将返回一个特定于个人的宠物列表。

  3. 处理器 基于 Pet-Person,您将根据自己的要求进行处理。

  4. 作家 根据您写入数据库的要求。

低级代码 sn-p:

  1. Partitioner

    public class PetPersonPartitioner implements Partitioner {
    
      @Autowired
      private PersonDAO personDAO;
    
      @Override
      public Map<String, ExecutionContext> partition(int gridSize) {
    
        Map<String, ExecutionContext> queue = new HashMap<String, ExecutionContext>();
    
        List<Person> personList = this.personDAO.getAllPersons();
        for (Person person : personList) {
    
          ExecutionContext ec = new ExecutionContext();
          ec.put("person", person);
          ec.put("personId", person.getId());
    
          queue.put(person.getId(), ec);
        }
    
      return queue;
      }
    }
    
  2. Reader

    <bean id="petByPersonIdRowMapper" class="yourpackage.PetByPersonIdRowMapper" />
    
    <bean id="petByPesonIdStatementSetter" scope="step"
          class="org.springframework.batch.core.resource.ListPreparedStatementSetter">
        <property name="parameters">
            <list>
                <value>#{stepExecutionContext['personId']}</value>
            </list>
        </property>
    </bean>
    
public class PetByPersonIdRowMapper implements RowMapper<PersonPetDetails> {
    @Override
    public BillingFeeConfigEntity mapRow(ResultSet rs, int rowNum) throws SQLException {
        PersonPetDetails record = new PersonPetDetails();

        record.setPersonId(rs.getLong("personId"));
      record.setPetId(rs.getLong("petid");
      ...
      ...
}
  1. Processor 您可以继续处理每个 PersonPetDetails 对象。

【讨论】:

  • 我想要一个 PersonPetDetails 对象,并且基于该对象,我必须在后续步骤中读取多个文件。你认为 tasklet 会比 partitioner 更合适吗?
猜你喜欢
  • 2019-06-04
  • 2017-03-23
  • 1970-01-01
  • 2021-06-23
  • 2013-09-30
  • 1970-01-01
  • 2018-01-16
  • 2016-07-19
  • 1970-01-01
相关资源
最近更新 更多