在spring批处理作业的读取器中实现键集分页
我有一个spring批处理作业,它从Postgres数据库中获取数据,并在处理后将数据写入excel工作表。但我想在spring批处理作业的读取器中实现键集分页。目前,我使用的是使用限制偏移量分页的JpaPagingItemReader,但由于我处理大量数据,JpaPagingItemReader用于获取数据的查询会随着偏移量的增加而变得效率低下。键集分页可以用来避免限制偏移量分页的限制,但我不知道如何实现具有键集分页的读取器。我如何实现它 编辑: 键集分页不包括记录的偏移/跳过,相反,我们将对结果中的数字唯一标识符进行排序和跟踪,并请求大于最后一个唯一条目的条目。在这个方法中,SQL如下所示(假设customer_id是记录的唯一自动生成标识符) 在实现键集分页时,需要记住以下几点:在spring批处理作业的读取器中实现键集分页,spring,pagination,spring-batch,Spring,Pagination,Spring Batch,我有一个spring批处理作业,它从Postgres数据库中获取数据,并在处理后将数据写入excel工作表。但我想在spring批处理作业的读取器中实现键集分页。目前,我使用的是使用限制偏移量分页的JpaPagingItemReader,但由于我处理大量数据,JpaPagingItemReader用于获取数据的查询会随着偏移量的增加而变得效率低下。键集分页可以用来避免限制偏移量分页的限制,但我不知道如何实现具有键集分页的读取器。我如何实现它 编辑: 键集分页不包括记录的偏移/跳过,相反,我们将对
公共类CustomerProcessorService{
公众客户(){
列出客户=新建ArrayList();
长lastCusId=0;
int size=100;
while(true){
//创建一个PageRequest对象,该对象将作为可分页接口传递给repo
//请注意,这里我们将0设置为偏移量
PageRequest PageRequest=新的PageRequest(0,大小);
//获取最后一个CUSID
lastCusId=getLastCusId(客户);
//从数据库中获取数据
customers=customerRepository.findbystatus和customeridgreatertanorderbycustomeridasc('ACTIVE',lastCusId,pageRequest);
//检查是否有数据
if(customers==null | | customers.isEmpty()){
打破
}
//处理
}
}
公共长getLastCusId(列出客户){
//如果传递的条目为null或空,则返回0(这将处理第一个迭代案例)
if(customers==null | | customers.isEmpty())
返回0升;
//按照每个客户的客户id对客户列表进行逻辑排序
//客户对象
//返回最后一个条目
返回customers.get(customers.size()-1.getCustomerId();
}
您应该能够通过扩展AbstractPaginatedDataItemReader
类来实现分页逻辑。这个基类处理大部分分页样板文件,并允许您在doPageRead
中指定分页逻辑。下面是一个快速示例,我将让您相应地调整它:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.springframework.batch.item.data.AbstractPaginatedDataItemReader;
import org.springframework.data.domain.PageRequest;
public class KeySetPagingItemReader extends AbstractPaginatedDataItemReader<Customer> {
long lastCusId = 0;
int size = 100;
private CustomerRepository customerRepository;
List<Customer> customers = new ArrayList();
public KeySetPagingItemReader(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
}
@Override
protected Iterator<Customer> doPageRead() {
PageRequest pageRequest = PageRequest.of(0,size);
// Get the lastCusId
lastCusId = getLastCusId(customers);
// Get the data from the database
customers = customerRepository.findByStatusAndCustomerIdGreaterThanOrderByCustomerIdAsc('ACTIVE',lastCusId,pageRequest);
return customers.iterator();
}
public Long getLastCusId(List<Customer> customers) {
// If passed entry is null or empty, return 0 ( This handles the first iteration case )
if ( customers == null || customers.isEmpty())
return 0l;
// Do the logic to sort the customers list by customer_id of each
// Customer object
// Return the last entry
return customers.get(customers.size() -1).getCustomerId();
}
}
import java.util.ArrayList;
导入java.util.Iterator;
导入java.util.List;
导入org.springframework.batch.item.data.AbstractPaginatedDataItemReader;
导入org.springframework.data.domain.PageRequest;
公共类KeySetPagingItemReader扩展了AbstractPaginatedDataItemReader{
长lastCusId=0;
int size=100;
私人客户存储客户存储;
列出客户=新建ArrayList();
public KeySetPagingItemReader(CustomerRepository CustomerRepository){
this.customerRepository=customerRepository;
}
@凌驾
受保护迭代器doPageRead(){
PageRequest PageRequest=PageRequest.of(0,大小);
//获取最后一个CUSID
lastCusId=getLastCusId(客户);
//从数据库中获取数据
customers=customerRepository.findbystatus和customeridgreatertanorderbycustomeridasc('ACTIVE',lastCusId,pageRequest);
return customers.iterator();
}
公共长getLastCusId(列出客户){
//如果传递的条目为null或空,则返回0(这将处理第一个迭代案例)
if(customers==null | | customers.isEmpty())
返回0升;
//按照每个客户的客户id对客户列表进行逻辑排序
//客户对象
//返回最后一个条目
返回customers.get(customers.size()-1.getCustomerId();
}
}
你能解释什么是键集分页吗?没有Spring Batch,你会怎么做?如果你分享你的代码,我可以帮助你用它创建一个Spring批处理读取器。@MahmoudBenHassine我添加了一个简短的解释以及实现键集分页的伪代码。我们如何在Spring批处理读取器中使用它?好的,谢谢你的更新。我添加了一个答案,其中包含一个需要编译/改编的示例。希望能有所帮助。@MahmoudBenHassine感谢您的答案。我还有一个疑问,如果lastCusId是UUID,则lastCusId的初始值应该是多少如果您的customerId是UUID,则说明中的第1点和第2点不再有效,并且此“键集分页”该技术将不再有效。您需要找到另一个标准来对数据进行排序/分页。我们是否也可以在此处使用AbstractPagingItemReader?AbstractPagingDataItemReader和AbstractPagingItemReader之间的区别是什么?是的,您可以。它们确实很相似,但在处理分页的方式上有细微的区别。AbstractPaginatedDataItemReader是按照Spring数据处理分页的方式设计的。
public class CustomerProcessorService {
public void processCustomers() {
List<Customer> customers = new ArrayList();
long lastCusId = 0;
int size = 100;
while ( true ) {
// Create a PageRequest object that will be passed as Pageable interface to repo
// Note that here we are setting 0 as the offset
PageRequest pageRequest = new PageRequest(0,size);
// Get the lastCusId
lastCusId = getLastCusId(customers);
// Get the data from the database
customers = customerRepository.findByStatusAndCustomerIdGreaterThanOrderByCustomerIdAsc('ACTIVE',lastCusId,pageRequest);
// Check if data is there
if ( customers == null || customers.isEmpty()) {
break;
}
// Do the processing
}
}
public Long getLastCusId(List<Customer> customers) {
// If passed entry is null or empty, return 0 ( This handles the first iteration case )
if ( customers == null || customers.isEmpty())
return 0l;
// Do the logic to sort the customers list by customer_id of each
// Customer object
// Return the last entry
return customers.get(customers.size() -1).getCustomerId();
}
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.springframework.batch.item.data.AbstractPaginatedDataItemReader;
import org.springframework.data.domain.PageRequest;
public class KeySetPagingItemReader extends AbstractPaginatedDataItemReader<Customer> {
long lastCusId = 0;
int size = 100;
private CustomerRepository customerRepository;
List<Customer> customers = new ArrayList();
public KeySetPagingItemReader(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
}
@Override
protected Iterator<Customer> doPageRead() {
PageRequest pageRequest = PageRequest.of(0,size);
// Get the lastCusId
lastCusId = getLastCusId(customers);
// Get the data from the database
customers = customerRepository.findByStatusAndCustomerIdGreaterThanOrderByCustomerIdAsc('ACTIVE',lastCusId,pageRequest);
return customers.iterator();
}
public Long getLastCusId(List<Customer> customers) {
// If passed entry is null or empty, return 0 ( This handles the first iteration case )
if ( customers == null || customers.isEmpty())
return 0l;
// Do the logic to sort the customers list by customer_id of each
// Customer object
// Return the last entry
return customers.get(customers.size() -1).getCustomerId();
}
}