CustomItemReader从DAO检索列表

时间:2015-11-02 14:16:30

标签: spring-batch

我有一个DAO类来从Hibernate中检索一组数据。

   <batch:step id="firstStep">
        <batch:tasklet>
            <batch:chunk reader="firstReader" writer="firstWriter"
                processor="itemProcessor" commit-interval="2">
            </batch:chunk>
        </batch:tasklet>
    </batch:step>

<bean id="firstReader" class="com.process.MyReader"
    scope="step">
</bean>

在我的读者中,我会在读取之前调用DAO来获取数据。

public class MyReader implements ItemReader<JobInstance>{

private List<JobInstance> jobList;
private String currentDate;
@Autowired
private JobDAO perDAO;

@BeforeRead
public void init() {
    //jobList= perDAO.getPersonAJobList(currentDate);
}

@Override
public JobInstance read() throws Exception, UnexpectedInputException,
        ParseException, NonTransientResourceException {
    return !jobList.isEmpty() ? jobList.remove(0) : null;
}

@Value("#{jobParameters['currentDate']}")
public void setCurrentDate(String currentDate) {
    this.currentDate = currentDate;
}

@Override
public void beforeStep(StepExecution stepExecution) {
    // TODO Auto-generated method stub
}

@Override
public ExitStatus afterStep(StepExecution stepExecution) {
    // TODO Auto-generated method stub
    return null;
}

}

当我运行批处理作业时,批处理作业会不断重复读取和处理。

[org.springframework.batch.repeat.support.RepeatTemplate] [getNextResult] [372] - Repeat operation about to start at count=1

以下是我的DAO课程

@Autowired
private QueryManager queryManager;

@Autowired
public JobDAO Impl(SessionFactory sessionFactory) {
    super(sessionFactory, JobInstance.class);
}

public List<JobInstance> getPersonAJobList(String currentDate) {
    String sql = queryManager.getNamedQuery("getJobList");
    System.out.println("---------------------- " + sql + "  " + currentDate);
    SQLQuery query = this.getCurrentSession().createSQLQuery(sql);
    query.setParameter("current_date", currentDate);
     .... 
    return result;
}

3 个答案:

答案 0 :(得分:0)

如果你在@BeforeRead注释方法中填写列表,那么列表将在每次读取之前更新

请参阅http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/core/annotation/BeforeRead.html

Marks a method to be called before an item is read from an ItemReader 

如果您需要从DAO获取项目,则需要考虑

的实现
  • 简单方法 - 保留当前实现,但在BeforeRead中添加一个检查以仅启动列表
  • 一个有状态的DAO,它填充列表一次并删除每个项目 读电话
  • 带有分页的无状态DAO

更好的方法是将数据访问(SQL)移动到批处理中,Spring Batch为SQL,Hibernate等提供了开箱即用的读者...请参阅http://docs.spring.io/spring-batch/reference/html/listOfReadersAndWriters.html

答案 1 :(得分:0)

init方法只应调用一次。执行此操作的正确方法是实现InitializingBean接口并实现afterPropertiesSet方法,或使用@PostConstruct注释而不是@BeforeRead。

使用@BeforeRead绝对是错误的,毫无意义。

正如Michael对答案的评论中所提到的,您还应该考虑使用标准读取器之一来从db获取数据。如果你从getPersonAJobList中获得几百或几千个条目就不会有问题,但是如果你得到数百万个条目,那肯定是错误的方法。

答案 2 :(得分:0)

如何在阅读器中添加“init”标志?进入MyReader.read()

  1. 如果未设置标记,请致电jobDAO以填充jobList并设置标记
  2. 如果设置了flag,则消耗jobList个项目。
  3. 小心使用jobList.remove(0),因为您的阅读器似乎无法重启;您需要将最后使用的项目索引维护到执行上下文中,以便从最后一个未提交的块的第一项继续重新启动。