我使用FlatFileItemReader创建了一个Spring批处理作业,它从分隔文件中读取数据,然后使用JdbcBatchItemWriter写入DB。我的setp配置如下所示。
<batch:step id="step1">
<batch:tasklet>
<batch:chunk reader="fileReader"
writer="dbWriter" commit-interval="100">
</batch:chunk>
</batch:tasklet>
</batch:step>
上面的配置为每100个开放单独的事务,因此如果在完成tasklet(步骤1)之前发生故障,那么我无法恢复先前提交的行。有没有办法在单个事务中运行整个tasklet?。
P.S:我使用MapJobRepositoryFactoryBean作为工作存储库,不想在数据库中创建元表以重新启动。
答案 0 :(得分:0)
在Spring批处理中,作业一次只能有一个事务。
请注意下图,因为我们可以看到事务在步骤开始时打开,并在步骤结束时提交。
事实上,使用spring批次的一个主要优点是我们作为开发人员不必担心事务管理。即使出现故障,它也会自动回滚整个未提交的事务。
答案 1 :(得分:0)
(自从我上次使用Spring Batch以来已经有一段时间了,我希望我的理解仍然有效:P)您可以简单地创建一个简单的tasklet,而不是使用面向chuck的tasklet。默认情况下,一个简单的tasklet将在单个事务中运行。鉴于你已经构建了读者和编写器,你可以编写一个模拟面向chuck的步骤的tasklet(只是伪代码向你展示这个想法):
public class ReaderWriterTasklet<T> implements Tasklet {
private ItemReader<T> reader;
private ItemWriter<T> writer;
// and corresponding setters
public RepeatStatus execute(StepContribution contribution,
ChunkContext chunkContext) {
List<T> chunk = new LinkedList<T>();
while (true) {
T item = reader.read();
if (item == null) {
break;
} else {
chunk.add(item);
}
}
writer.write(chunk);
return RepeatStatus.FINISHED;
}
}
(我相信你应该已经知道如何定义运行tasklet的步骤了吗?我会跳过那个)
另一种脏方法是继续使用chunk,并将commit-interval设置为Integer.MAX_VALUE
。通过这样做,面向块的步骤将继续从读取器获取项目直到它到达结束,并在一个大块中写入编写器,这一切都发生在一个事务中。