首页 > 解决方案 > Spring Batch:我们如何从数据库中预加载值并将其用于处理器部分

问题描述

我有一个要求,我需要在 ItemProcessor 部分查找几个表。我不想对 ItemProcessor 部分中的每一行进行多次 JDBC 调用,当 Spring Batch 开始处理更多记录时,这可能会导致性能问题。避免这种情况的解决方法是什么?有没有办法在 ItemProcessor 或批处理开始之前预加载这些对象,并可以在 ItemProcessor 中引用它?

标签: spring-batch

解决方案


您可以在 Spring 应用程序上下文初始化期间使用 @PostConstruct 注释您的方法来读取数据。使您的 ItemReader 的读取方法从列表中返回值。当整个列表完成时返回 null。这将停止阅读。

@Service
public class YourItemReader implements ItemReader<DomainObject> {

 private int index;

 List<DomainObject> dbRows;

 @PostConstruct
 public void init() {
   List<DomainObject> //read from database
 }


@Override
public DomainObject read(){
        if (null != dbRows && index < dbRows.size()) {
         return dbRows.get(index);
       }
   return null;
}

如果记录数以百万计,我建议从您的数据库中进行基于块的读取,而不是一次读取所有记录,这可能会导致垃圾收集器内存不足异常。这可以通过在表中添加一个名为 STATUS 的列来轻松完成,以跟踪已处理记录的状态。最初,当您将数据加载到表中时,将状态设置为“未处理”,当您的 ItemReader 读取记录块时,将状态设置为“进行中”。一旦您的 ItemProcessor 或 ItemWriter 完成其处理,将状态从“IN PROGRESS”更改为“PROCESSED”。确保将从数据库中获取数据的方法设置为“同步”。这将确保多个线程不会从数据库中获取相同的数据。

public List<DomainObject> read(){
 return fetchDataFromDb();
}

private synchronized List<DomainObject> fetchProductAssociationData(){
//read your chunk-size of records from database which has status as 'NOT 
PROCESSED' 
 and change the status of the data which is read to 'IN PROGRESS'
return list;
}

推荐阅读