将行写入 csv 文件时,如何在 Spring 批处理中的 FlatFileItemWriter 中包含一个计数器
How to include a counter in FlatFileItemWriter in Spring Batch when writing rows to a csv file
因此,我正在使用 FlatFileItemWriter 从我可以从数据库中成功读取的数据写入一个 csv 文件。
我正在为如何写入与我正在写入文件的行相对应的整数(即行计数器)而苦苦挣扎。看起来很容易做,但很简单,我很难过。
一切正常(正在根据从数据库读取的数据生成文件)。但我似乎无法弄清楚如何以获取相应行数的方式实现我的 getCount() 方法。我认为这与利用 ChunkContext 有关,但我似乎无法弄清楚。
所以我的作业配置中的 bean 中有以下内容。
@Bean
public FlatFileItemWriter<Customer> customerItemWriter() throws Exception {
FlatFileItemWriter<Customer> itemWriter = new FlatFileItemWriter<>();
itemWriter.setLineAggregator(new CustomerLineAggregator());
itemWriter.setResource(new FileSystemResource("/some/directory/file.csv"));
itemWriter.afterPropertiesSet();
return itemWriter;
}
我还有以下 LineAggregator 实现。
public class CustomerLineAggregator implements LineAggregator<Customer> {
private ChunkContext chunkContext;
@BeforeChunk
private void beforeChunk(ChunkContext chunkContext) {
this.setChunkContext(chunkContext);
}
@Override
public String aggregate(Customer item) {
return getCount() + "," + convertTime(item.getTime(), 3) + " ET," + item.getCustomerId() + "," + item.getLink() + "," + item.getName();
}
private String convertTime(String timeString, int offset) {
LocalTime timeObject = LocalTime.parse(timeString);
LocalTime timeOffsetObject = timeObject.plusHours(offset);
return timeOffsetObject.toString();
}
private String getCount() {
// how do I make use of the chunk context to infer the integer corresponding to the item assuming my chunk size is 1.
return someCountString;
}
public ChunkContext getChunkContext() {
return chunkContext;
}
public void setChunkContext(ChunkContext chunkContext) {
this.chunkContext = chunkContext;
}
}
预期的输出文件应如下所示:
1, 10:09 ET, 742, https://www.firm.com, John Doe
2, 12:30 ET, 235, http://www.firm.com, Jane Doe
3, 9:21 ET, 398, http://www.thomas.io, Thomas Chan
4, 14:38 ET, 104, http://www.googl.com, Cindy Chen
除了第一列,我可以成功生成以上内容,第一列只是每条记录的行数。我尝试过的任何操作都无法在作业运行之间自行重置。
您可以为此使用 ItemCountAware 界面。该接口由您的域对象(在您的情况下似乎是 Customer
)实现,并且将在阅读时由扩展 AbstractItemCountingItemStreamItemReader
.
的任何 reader 调用
因此,如果您的 reader 是其中之一,您可以获取项目的项目计数并根据需要在 LineAggregator
中使用它。
编辑:当 reader 不扩展 AbstractItemCountingItemStreamItemReader
时添加选项
您始终可以在 ItemReadListener#afterRead
中分配项目编号并在您的聚合器中使用它,例如:
class ItemNumberListener implements ItemReadListener<Customer> {
int number;
@Override
public void afterRead(Customer customer) {
customer.setNumber(number++);
}
// other methods from ItemReadListener
}
一旦到位,您就可以在您的步骤中注册此侦听器并在您的 LineAggregator
中使用项目编号。此方法适用于所有 readers(基于光标或基于分页)。
NB:如果你不能在Customer
对象中添加一个字段+getter/setter(可能是一个你不能修改的class),你可以将它包裹在一个像 NumberAwareCustomer
这样的自定义对象并在您的批处理应用程序中使用该类型。
因此,我正在使用 FlatFileItemWriter 从我可以从数据库中成功读取的数据写入一个 csv 文件。
我正在为如何写入与我正在写入文件的行相对应的整数(即行计数器)而苦苦挣扎。看起来很容易做,但很简单,我很难过。
一切正常(正在根据从数据库读取的数据生成文件)。但我似乎无法弄清楚如何以获取相应行数的方式实现我的 getCount() 方法。我认为这与利用 ChunkContext 有关,但我似乎无法弄清楚。
所以我的作业配置中的 bean 中有以下内容。
@Bean
public FlatFileItemWriter<Customer> customerItemWriter() throws Exception {
FlatFileItemWriter<Customer> itemWriter = new FlatFileItemWriter<>();
itemWriter.setLineAggregator(new CustomerLineAggregator());
itemWriter.setResource(new FileSystemResource("/some/directory/file.csv"));
itemWriter.afterPropertiesSet();
return itemWriter;
}
我还有以下 LineAggregator 实现。
public class CustomerLineAggregator implements LineAggregator<Customer> {
private ChunkContext chunkContext;
@BeforeChunk
private void beforeChunk(ChunkContext chunkContext) {
this.setChunkContext(chunkContext);
}
@Override
public String aggregate(Customer item) {
return getCount() + "," + convertTime(item.getTime(), 3) + " ET," + item.getCustomerId() + "," + item.getLink() + "," + item.getName();
}
private String convertTime(String timeString, int offset) {
LocalTime timeObject = LocalTime.parse(timeString);
LocalTime timeOffsetObject = timeObject.plusHours(offset);
return timeOffsetObject.toString();
}
private String getCount() {
// how do I make use of the chunk context to infer the integer corresponding to the item assuming my chunk size is 1.
return someCountString;
}
public ChunkContext getChunkContext() {
return chunkContext;
}
public void setChunkContext(ChunkContext chunkContext) {
this.chunkContext = chunkContext;
}
}
预期的输出文件应如下所示:
1, 10:09 ET, 742, https://www.firm.com, John Doe
2, 12:30 ET, 235, http://www.firm.com, Jane Doe
3, 9:21 ET, 398, http://www.thomas.io, Thomas Chan
4, 14:38 ET, 104, http://www.googl.com, Cindy Chen
除了第一列,我可以成功生成以上内容,第一列只是每条记录的行数。我尝试过的任何操作都无法在作业运行之间自行重置。
您可以为此使用 ItemCountAware 界面。该接口由您的域对象(在您的情况下似乎是 Customer
)实现,并且将在阅读时由扩展 AbstractItemCountingItemStreamItemReader
.
因此,如果您的 reader 是其中之一,您可以获取项目的项目计数并根据需要在 LineAggregator
中使用它。
编辑:当 reader 不扩展 AbstractItemCountingItemStreamItemReader
您始终可以在 ItemReadListener#afterRead
中分配项目编号并在您的聚合器中使用它,例如:
class ItemNumberListener implements ItemReadListener<Customer> {
int number;
@Override
public void afterRead(Customer customer) {
customer.setNumber(number++);
}
// other methods from ItemReadListener
}
一旦到位,您就可以在您的步骤中注册此侦听器并在您的 LineAggregator
中使用项目编号。此方法适用于所有 readers(基于光标或基于分页)。
NB:如果你不能在Customer
对象中添加一个字段+getter/setter(可能是一个你不能修改的class),你可以将它包裹在一个像 NumberAwareCustomer
这样的自定义对象并在您的批处理应用程序中使用该类型。